/*
 * Copyright (C) 2023 Apple Inc. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 * Autogenerated, do not modify.
*/

#pragma once

#include "ArithProfile.h"
#include "BytecodeDumper.h"
#include "Fits.h"
#include "GetByIdMetadata.h"
#include "GetByValHistory.h"
#include "Instruction.h"
#include "IterationModeMetadata.h"
#include "Opcode.h"
#include "PrivateFieldPutKind.h"
#include "PutByIdStatus.h"
#include "PutByIdFlags.h"
#include "ToThisStatus.h"

namespace JSC {

void dumpBytecode(BytecodeDumperBase* dumper, InstructionStream::Offset, const Instruction*);

#if ENABLE(WEBASSEMBLY)
void dumpWasm(BytecodeDumperBase* dumper, InstructionStream::Offset, const Instruction*);
#endif // ENABLE(WEBASSEMBLY)


struct OpIteratorOpen : public Instruction {
    static constexpr OpcodeID opcodeID = op_iterator_open;
    static constexpr size_t length = 7;
    
    enum Checkpoints : uint8_t {
        symbolCall,
        getNext,
        numberOfCheckpoints,
    };


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister iterator, VirtualRegister next, VirtualRegister symbolIterator, VirtualRegister iterable, unsigned stackOffset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, iterator, next, symbolIterator, iterable, stackOffset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister iterator, VirtualRegister next, VirtualRegister symbolIterator, VirtualRegister iterable, unsigned stackOffset)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister iterator, VirtualRegister next, VirtualRegister symbolIterator, VirtualRegister iterable, unsigned stackOffset)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister iterator, VirtualRegister next, VirtualRegister symbolIterator, VirtualRegister iterable, unsigned stackOffset, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister iterator, VirtualRegister next, VirtualRegister symbolIterator, VirtualRegister iterable, unsigned stackOffset)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& iterator, VirtualRegister& next, VirtualRegister& symbolIterator, VirtualRegister& iterable, unsigned& stackOffset, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(iterator)
            && Fits<VirtualRegister, __size>::check(next)
            && Fits<VirtualRegister, __size>::check(symbolIterator)
            && Fits<VirtualRegister, __size>::check(iterable)
            && Fits<unsigned, __size>::check(stackOffset)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister iterator, VirtualRegister next, VirtualRegister symbolIterator, VirtualRegister iterable, unsigned stackOffset, unsigned __metadataID)
    {
        gen->setUsesCheckpoints();
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, iterator, next, symbolIterator, iterable, stackOffset, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(iterator));
            gen->write(Fits<VirtualRegister, __size>::convert(next));
            gen->write(Fits<VirtualRegister, __size>::convert(symbolIterator));
            gen->write(Fits<VirtualRegister, __size>::convert(iterable));
            gen->write(Fits<unsigned, __size>::convert(stackOffset));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**iterator_open"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("iterator", m_iterator, true);
        dumper->dumpOperand("next", m_next, false);
        dumper->dumpOperand("symbolIterator", m_symbolIterator, false);
        dumper->dumpOperand("iterable", m_iterable, false);
        dumper->dumpOperand("stackOffset", m_stackOffset, false);
    }

    OpIteratorOpen(const uint8_t* stream)
        : m_iterator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_next(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_symbolIterator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_iterable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIteratorOpen(const uint16_t* stream)
        : m_iterator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_next(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_symbolIterator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_iterable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIteratorOpen(const uint32_t* stream)
        : m_iterator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_next(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_symbolIterator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_iterable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIteratorOpen decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setIterator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIterator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIterator<OpcodeSize::Wide16>(value, func);
        else
            setIterator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIterator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNext(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setNext<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setNext<OpcodeSize::Wide16>(value, func);
        else
            setNext<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNext(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolIterator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSymbolIterator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSymbolIterator<OpcodeSize::Wide16>(value, func);
        else
            setSymbolIterator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSymbolIterator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIterable(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIterable<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIterable<OpcodeSize::Wide16>(value, func);
        else
            setIterable<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIterable(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide16>(value, func);
        else
            setStackOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_iterator_open;
        Metadata(const OpIteratorOpen&) { }

        IterationModeMetadata m_iterationMetadata;
        ValueProfile m_iterableProfile;
        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_iteratorProfile;
        GetByIdModeMetadata m_modeMetadata;
        ValueProfile m_nextProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_iterator;
    VirtualRegister m_next;
    VirtualRegister m_symbolIterator;
    VirtualRegister m_iterable;
    unsigned m_stackOffset;
    unsigned m_metadataID;
};
static_assert(OpIteratorOpen::length > OpIteratorOpen::numberOfCheckpoints, "FullBytecodeLivess relies on the length of OpIteratorOpen being greater than the number of checkpoints");

struct OpTailCallVarargs : public Instruction {
    static constexpr OpcodeID opcodeID = op_tail_call_varargs;
    static constexpr size_t length = 8;
    enum Tmps : uint8_t {
        argCountIncludingThis,
    };
    enum Checkpoints : uint8_t {
        determiningArgCount,
        makeCall,
        numberOfCheckpoints,
    };


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(arguments)
            && Fits<VirtualRegister, __size>::check(firstFree)
            && Fits<int, __size>::check(firstVarArg)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        gen->setUsesCheckpoints();
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(arguments));
            gen->write(Fits<VirtualRegister, __size>::convert(firstFree));
            gen->write(Fits<int, __size>::convert(firstVarArg));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**tail_call_varargs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("arguments", m_arguments, false);
        dumper->dumpOperand("firstFree", m_firstFree, false);
        dumper->dumpOperand("firstVarArg", m_firstVarArg, false);
    }

    OpTailCallVarargs(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTailCallVarargs(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTailCallVarargs(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTailCallVarargs decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide16>(value, func);
        else
            setArguments<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide16>(value, func);
        else
            setFirstFree<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide16>(value, func);
        else
            setFirstVarArg<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_tail_call_varargs;
        Metadata(const OpTailCallVarargs&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    VirtualRegister m_thisValue;
    VirtualRegister m_arguments;
    VirtualRegister m_firstFree;
    int m_firstVarArg;
    unsigned m_metadataID;
};
static_assert(OpTailCallVarargs::length > OpTailCallVarargs::numberOfCheckpoints, "FullBytecodeLivess relies on the length of OpTailCallVarargs being greater than the number of checkpoints");

struct OpConstructVarargs : public Instruction {
    static constexpr OpcodeID opcodeID = op_construct_varargs;
    static constexpr size_t length = 8;
    enum Tmps : uint8_t {
        argCountIncludingThis,
    };
    enum Checkpoints : uint8_t {
        determiningArgCount,
        makeCall,
        numberOfCheckpoints,
    };


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(arguments)
            && Fits<VirtualRegister, __size>::check(firstFree)
            && Fits<int, __size>::check(firstVarArg)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        gen->setUsesCheckpoints();
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(arguments));
            gen->write(Fits<VirtualRegister, __size>::convert(firstFree));
            gen->write(Fits<int, __size>::convert(firstVarArg));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**construct_varargs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("arguments", m_arguments, false);
        dumper->dumpOperand("firstFree", m_firstFree, false);
        dumper->dumpOperand("firstVarArg", m_firstVarArg, false);
    }

    OpConstructVarargs(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpConstructVarargs(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpConstructVarargs(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpConstructVarargs decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide16>(value, func);
        else
            setArguments<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide16>(value, func);
        else
            setFirstFree<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide16>(value, func);
        else
            setFirstVarArg<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_construct_varargs;
        Metadata(const OpConstructVarargs&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    VirtualRegister m_thisValue;
    VirtualRegister m_arguments;
    VirtualRegister m_firstFree;
    int m_firstVarArg;
    unsigned m_metadataID;
};
static_assert(OpConstructVarargs::length > OpConstructVarargs::numberOfCheckpoints, "FullBytecodeLivess relies on the length of OpConstructVarargs being greater than the number of checkpoints");

struct OpCallVarargs : public Instruction {
    static constexpr OpcodeID opcodeID = op_call_varargs;
    static constexpr size_t length = 8;
    enum Tmps : uint8_t {
        argCountIncludingThis,
    };
    enum Checkpoints : uint8_t {
        determiningArgCount,
        makeCall,
        numberOfCheckpoints,
    };


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(arguments)
            && Fits<VirtualRegister, __size>::check(firstFree)
            && Fits<int, __size>::check(firstVarArg)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        gen->setUsesCheckpoints();
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(arguments));
            gen->write(Fits<VirtualRegister, __size>::convert(firstFree));
            gen->write(Fits<int, __size>::convert(firstVarArg));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_varargs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("arguments", m_arguments, false);
        dumper->dumpOperand("firstFree", m_firstFree, false);
        dumper->dumpOperand("firstVarArg", m_firstVarArg, false);
    }

    OpCallVarargs(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCallVarargs(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCallVarargs(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCallVarargs decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide16>(value, func);
        else
            setArguments<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide16>(value, func);
        else
            setFirstFree<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide16>(value, func);
        else
            setFirstVarArg<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_call_varargs;
        Metadata(const OpCallVarargs&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    VirtualRegister m_thisValue;
    VirtualRegister m_arguments;
    VirtualRegister m_firstFree;
    int m_firstVarArg;
    unsigned m_metadataID;
};
static_assert(OpCallVarargs::length > OpCallVarargs::numberOfCheckpoints, "FullBytecodeLivess relies on the length of OpCallVarargs being greater than the number of checkpoints");

struct OpIteratorNext : public Instruction {
    static constexpr OpcodeID opcodeID = op_iterator_next;
    static constexpr size_t length = 8;
    enum Tmps : uint8_t {
        nextResult,
    };
    enum Checkpoints : uint8_t {
        computeNext,
        getDone,
        getValue,
        numberOfCheckpoints,
    };


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister done, VirtualRegister value, VirtualRegister iterable, VirtualRegister next, VirtualRegister iterator, unsigned stackOffset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, done, value, iterable, next, iterator, stackOffset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister done, VirtualRegister value, VirtualRegister iterable, VirtualRegister next, VirtualRegister iterator, unsigned stackOffset)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister done, VirtualRegister value, VirtualRegister iterable, VirtualRegister next, VirtualRegister iterator, unsigned stackOffset)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister done, VirtualRegister value, VirtualRegister iterable, VirtualRegister next, VirtualRegister iterator, unsigned stackOffset, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister done, VirtualRegister value, VirtualRegister iterable, VirtualRegister next, VirtualRegister iterator, unsigned stackOffset)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& done, VirtualRegister& value, VirtualRegister& iterable, VirtualRegister& next, VirtualRegister& iterator, unsigned& stackOffset, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(done)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(iterable)
            && Fits<VirtualRegister, __size>::check(next)
            && Fits<VirtualRegister, __size>::check(iterator)
            && Fits<unsigned, __size>::check(stackOffset)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister done, VirtualRegister value, VirtualRegister iterable, VirtualRegister next, VirtualRegister iterator, unsigned stackOffset, unsigned __metadataID)
    {
        gen->setUsesCheckpoints();
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, done, value, iterable, next, iterator, stackOffset, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(done));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(iterable));
            gen->write(Fits<VirtualRegister, __size>::convert(next));
            gen->write(Fits<VirtualRegister, __size>::convert(iterator));
            gen->write(Fits<unsigned, __size>::convert(stackOffset));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**iterator_next"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("done", m_done, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("iterable", m_iterable, false);
        dumper->dumpOperand("next", m_next, false);
        dumper->dumpOperand("iterator", m_iterator, false);
        dumper->dumpOperand("stackOffset", m_stackOffset, false);
    }

    OpIteratorNext(const uint8_t* stream)
        : m_done(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_iterable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_next(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_iterator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIteratorNext(const uint16_t* stream)
        : m_done(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_iterable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_next(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_iterator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIteratorNext(const uint32_t* stream)
        : m_done(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_iterable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_next(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_iterator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIteratorNext decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDone(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDone<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDone<OpcodeSize::Wide16>(value, func);
        else
            setDone<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDone(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIterable(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIterable<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIterable<OpcodeSize::Wide16>(value, func);
        else
            setIterable<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIterable(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNext(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setNext<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setNext<OpcodeSize::Wide16>(value, func);
        else
            setNext<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNext(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIterator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIterator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIterator<OpcodeSize::Wide16>(value, func);
        else
            setIterator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIterator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide16>(value, func);
        else
            setStackOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_iterator_next;
        Metadata(const OpIteratorNext&) { }

        IterationModeMetadata m_iterationMetadata;
        ArrayProfile m_iterableProfile;
        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_nextResultProfile;
        GetByIdModeMetadata m_doneModeMetadata;
        ValueProfile m_doneProfile;
        GetByIdModeMetadata m_valueModeMetadata;
        ValueProfile m_valueProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_done;
    VirtualRegister m_value;
    VirtualRegister m_iterable;
    VirtualRegister m_next;
    VirtualRegister m_iterator;
    unsigned m_stackOffset;
    unsigned m_metadataID;
};
static_assert(OpIteratorNext::length > OpIteratorNext::numberOfCheckpoints, "FullBytecodeLivess relies on the length of OpIteratorNext being greater than the number of checkpoints");

struct OpGetByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_val;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpGetByVal(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetByVal(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetByVal(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetByVal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_by_val;
        Metadata(const OpGetByVal&) { }

        ValueProfile m_profile;
        ArrayProfile m_arrayProfile;
        GetByValHistory m_seenIdentifiers;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_metadataID;
};


struct OpGetPrivateName : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_private_name;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_private_name"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpGetPrivateName(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetPrivateName(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetPrivateName(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetPrivateName decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_private_name;
        Metadata(const OpGetPrivateName&) { }

        ValueProfile m_profile;
        StructureID m_structureID;
        unsigned m_offset;
        WriteBarrier<JSCell> m_property;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_metadataID;
};


struct OpGetByIdDirect : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_id_direct;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_id_direct"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpGetByIdDirect(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetByIdDirect(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetByIdDirect(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetByIdDirect decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_by_id_direct;
        Metadata(const OpGetByIdDirect&) { }

        ValueProfile m_profile;
        StructureID m_structureID;
        unsigned m_offset;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
    unsigned m_metadataID;
};


struct OpPutPrivateName : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_private_name;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, PrivateFieldPutKind putKind)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, value, putKind);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, PrivateFieldPutKind putKind)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, base, property, value, putKind, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, PrivateFieldPutKind putKind)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, base, property, value, putKind, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, PrivateFieldPutKind putKind, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, value, putKind, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, PrivateFieldPutKind putKind)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, value, putKind, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, value, putKind, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, value, putKind, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, PrivateFieldPutKind& putKind, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<PrivateFieldPutKind, __size>::check(putKind)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, PrivateFieldPutKind putKind, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, value, putKind, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<PrivateFieldPutKind, __size>::convert(putKind));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_private_name"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("putKind", m_putKind, false);
    }

    OpPutPrivateName(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_putKind(Fits<PrivateFieldPutKind, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutPrivateName(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_putKind(Fits<PrivateFieldPutKind, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutPrivateName(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_putKind(Fits<PrivateFieldPutKind, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutPrivateName decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPutKind(PrivateFieldPutKind value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setPutKind<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setPutKind<OpcodeSize::Wide16>(value, func);
        else
            setPutKind<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPutKind(PrivateFieldPutKind value, Functor func)
    {
        if (!Fits<PrivateFieldPutKind, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<PrivateFieldPutKind, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_put_private_name;
        Metadata(const OpPutPrivateName&) { }

        StructureID m_oldStructureID;
        WriteBarrier<JSCell> m_property;
        unsigned m_offset;
        StructureID m_newStructureID;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_value;
    PrivateFieldPutKind m_putKind;
    unsigned m_metadataID;
};


struct OpAdd : public Instruction {
    static constexpr OpcodeID opcodeID = op_add;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<OperandTypes, __size>::check(operandTypes)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<OperandTypes, __size>::convert(operandTypes));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("operandTypes", m_operandTypes, false);
    }

    OpAdd(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpAdd(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpAdd(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpAdd decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide16>(value, func);
        else
            setOperandTypes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (!Fits<OperandTypes, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_add;
        Metadata(const OpAdd&) { }

        BinaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    OperandTypes m_operandTypes;
    unsigned m_metadataID;
};


struct OpGetArgument : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_argument;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, int index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, index);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, int index)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, index, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, int index)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, index, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, int index, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, index, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, int index)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, index, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, index, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, index, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, int& index, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<int, __size>::check(index)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, int index, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, index, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<int, __size>::convert(index));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_argument"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("index", m_index, false);
    }

    OpGetArgument(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_index(Fits<int, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetArgument(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_index(Fits<int, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetArgument(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_index(Fits<int, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetArgument decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_argument;
        Metadata(const OpGetArgument&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    int m_index;
    unsigned m_metadataID;
};


struct OpTryGetById : public Instruction {
    static constexpr OpcodeID opcodeID = op_try_get_by_id;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**try_get_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpTryGetById(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTryGetById(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTryGetById(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTryGetById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_try_get_by_id;
        Metadata(const OpTryGetById&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
    unsigned m_metadataID;
};


struct OpCall : public Instruction {
    static constexpr OpcodeID opcodeID = op_call;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, argc, argv);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, argc, argv, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(argc)
            && Fits<unsigned, __size>::check(argv)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, argc, argv, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(argc));
            gen->write(Fits<unsigned, __size>::convert(argv));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("argc", m_argc, false);
        dumper->dumpOperand("argv", m_argv, false);
    }

    OpCall(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCall(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCall(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCall decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide16>(value, func);
        else
            setArgc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide16>(value, func);
        else
            setArgv<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_call;
        Metadata(const OpCall&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_argc;
    unsigned m_argv;
    unsigned m_metadataID;
};


struct OpTailCall : public Instruction {
    static constexpr OpcodeID opcodeID = op_tail_call;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, argc, argv);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, argc, argv, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(argc)
            && Fits<unsigned, __size>::check(argv)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, argc, argv, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(argc));
            gen->write(Fits<unsigned, __size>::convert(argv));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**tail_call"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("argc", m_argc, false);
        dumper->dumpOperand("argv", m_argv, false);
    }

    OpTailCall(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTailCall(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTailCall(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTailCall decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide16>(value, func);
        else
            setArgc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide16>(value, func);
        else
            setArgv<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_tail_call;
        Metadata(const OpTailCall&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_argc;
    unsigned m_argv;
    unsigned m_metadataID;
};


struct OpCallEval : public Instruction {
    static constexpr OpcodeID opcodeID = op_call_eval;
    static constexpr size_t length = 7;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, argc, argv, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, ECMAMode ecmaMode)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, argc, argv, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, ECMAMode ecmaMode)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, argc, argv, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, ECMAMode ecmaMode, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, argc, argv, ecmaMode, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, ECMAMode ecmaMode)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, ecmaMode, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, ecmaMode, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, argc, argv, ecmaMode, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, ECMAMode& ecmaMode, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(argc)
            && Fits<unsigned, __size>::check(argv)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, ECMAMode ecmaMode, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, argc, argv, ecmaMode, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(argc));
            gen->write(Fits<unsigned, __size>::convert(argv));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_eval"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("argc", m_argc, false);
        dumper->dumpOperand("argv", m_argv, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpCallEval(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCallEval(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCallEval(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCallEval decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide16>(value, func);
        else
            setArgc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide16>(value, func);
        else
            setArgv<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_call_eval;
        Metadata(const OpCallEval&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_argc;
    unsigned m_argv;
    ECMAMode m_ecmaMode;
    unsigned m_metadataID;
};


struct OpTailCallForwardArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_tail_call_forward_arguments;
    static constexpr size_t length = 8;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, VirtualRegister& thisValue, VirtualRegister& arguments, VirtualRegister& firstFree, int& firstVarArg, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(arguments)
            && Fits<VirtualRegister, __size>::check(firstFree)
            && Fits<int, __size>::check(firstVarArg)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, VirtualRegister thisValue, VirtualRegister arguments, VirtualRegister firstFree, int firstVarArg, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(arguments));
            gen->write(Fits<VirtualRegister, __size>::convert(firstFree));
            gen->write(Fits<int, __size>::convert(firstVarArg));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**tail_call_forward_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("arguments", m_arguments, false);
        dumper->dumpOperand("firstFree", m_firstFree, false);
        dumper->dumpOperand("firstVarArg", m_firstVarArg, false);
    }

    OpTailCallForwardArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTailCallForwardArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTailCallForwardArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_firstFree(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_firstVarArg(Fits<int, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTailCallForwardArguments decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide16>(value, func);
        else
            setArguments<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstFree<OpcodeSize::Wide16>(value, func);
        else
            setFirstFree<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFirstVarArg<OpcodeSize::Wide16>(value, func);
        else
            setFirstVarArg<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_tail_call_forward_arguments;
        Metadata(const OpTailCallForwardArguments&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    VirtualRegister m_thisValue;
    VirtualRegister m_arguments;
    VirtualRegister m_firstFree;
    int m_firstVarArg;
    unsigned m_metadataID;
};


struct OpConstruct : public Instruction {
    static constexpr OpcodeID opcodeID = op_construct;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, argc, argv);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, argc, argv, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, argc, argv, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& argc, unsigned& argv, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(argc)
            && Fits<unsigned, __size>::check(argv)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, argc, argv, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(argc));
            gen->write(Fits<unsigned, __size>::convert(argv));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**construct"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("argc", m_argc, false);
        dumper->dumpOperand("argv", m_argv, false);
    }

    OpConstruct(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpConstruct(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpConstruct(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_argv(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpConstruct decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide16>(value, func);
        else
            setArgc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide16>(value, func);
        else
            setArgv<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_construct;
        Metadata(const OpConstruct&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_argc;
    unsigned m_argv;
    unsigned m_metadataID;
};


struct OpNewArrayWithSize : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array_with_size;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, length);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, length, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, length, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, length, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, length, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, length, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, length, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& length, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(length)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister length, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, length, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(length));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array_with_size"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("length", m_length, false);
    }

    OpNewArrayWithSize(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewArrayWithSize(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewArrayWithSize(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewArrayWithSize decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLength<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLength<OpcodeSize::Wide16>(value, func);
        else
            setLength<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_new_array_with_size;
        Metadata(const OpNewArrayWithSize&) { }

        ArrayAllocationProfile m_arrayAllocationProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_length;
    unsigned m_metadataID;
};


struct OpNewObject : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_object;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, inlineCapacity);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, inlineCapacity, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, inlineCapacity, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, inlineCapacity, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, inlineCapacity, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, inlineCapacity, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, inlineCapacity, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& inlineCapacity, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<unsigned, __size>::check(inlineCapacity)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned inlineCapacity, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, inlineCapacity, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<unsigned, __size>::convert(inlineCapacity));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("inlineCapacity", m_inlineCapacity, false);
    }

    OpNewObject(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_inlineCapacity(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewObject(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewObject(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewObject decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInlineCapacity(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setInlineCapacity<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setInlineCapacity<OpcodeSize::Wide16>(value, func);
        else
            setInlineCapacity<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setInlineCapacity(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_new_object;
        Metadata(const OpNewObject&) { }

        ObjectAllocationProfile m_objectAllocationProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    unsigned m_inlineCapacity;
    unsigned m_metadataID;
};


struct OpGetByIdWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_id_with_this;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, thisValue, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, thisValue, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, thisValue, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, thisValue, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, thisValue, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& thisValue, unsigned& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, unsigned property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, thisValue, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_id_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpGetByIdWithThis(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetByIdWithThis(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetByIdWithThis(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetByIdWithThis decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_by_id_with_this;
        Metadata(const OpGetByIdWithThis&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_thisValue;
    unsigned m_property;
    unsigned m_metadataID;
};


struct OpMul : public Instruction {
    static constexpr OpcodeID opcodeID = op_mul;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<OperandTypes, __size>::check(operandTypes)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<OperandTypes, __size>::convert(operandTypes));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mul"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("operandTypes", m_operandTypes, false);
    }

    OpMul(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpMul(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpMul(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpMul decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide16>(value, func);
        else
            setOperandTypes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (!Fits<OperandTypes, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_mul;
        Metadata(const OpMul&) { }

        BinaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    OperandTypes m_operandTypes;
    unsigned m_metadataID;
};


struct OpDiv : public Instruction {
    static constexpr OpcodeID opcodeID = op_div;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<OperandTypes, __size>::check(operandTypes)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<OperandTypes, __size>::convert(operandTypes));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**div"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("operandTypes", m_operandTypes, false);
    }

    OpDiv(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDiv(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDiv(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDiv decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide16>(value, func);
        else
            setOperandTypes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (!Fits<OperandTypes, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_div;
        Metadata(const OpDiv&) { }

        BinaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    OperandTypes m_operandTypes;
    unsigned m_metadataID;
};


struct OpPutByValDirect : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_val_direct;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, value, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, base, property, value, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, base, property, value, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, value, ecmaMode, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, value, ecmaMode, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, value, ecmaMode, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, value, ecmaMode, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, ECMAMode& ecmaMode, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, value, ecmaMode, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_val_direct"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpPutByValDirect(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutByValDirect(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutByValDirect(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutByValDirect decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_put_by_val_direct;
        Metadata(const OpPutByValDirect&) { }

        ArrayProfile m_arrayProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_value;
    ECMAMode m_ecmaMode;
    unsigned m_metadataID;
};


struct OpGetPrototypeOf : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_prototype_of;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, value, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, value, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, value, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, value, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, value, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, value, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, value, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_prototype_of"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("value", m_value, false);
    }

    OpGetPrototypeOf(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetPrototypeOf(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetPrototypeOf(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetPrototypeOf decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_prototype_of;
        Metadata(const OpGetPrototypeOf&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_value;
    unsigned m_metadataID;
};


struct OpCreateThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_this;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, inlineCapacity);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, inlineCapacity, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, inlineCapacity, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, inlineCapacity, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, inlineCapacity, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned& inlineCapacity, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(inlineCapacity)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned inlineCapacity, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, inlineCapacity, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(inlineCapacity));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("inlineCapacity", m_inlineCapacity, false);
    }

    OpCreateThis(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_inlineCapacity(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateThis(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateThis(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_inlineCapacity(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateThis decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInlineCapacity(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setInlineCapacity<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setInlineCapacity<OpcodeSize::Wide16>(value, func);
        else
            setInlineCapacity<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setInlineCapacity(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_create_this;
        Metadata(const OpCreateThis&) { }

        WriteBarrier<JSCell> m_cachedCallee;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_inlineCapacity;
    unsigned m_metadataID;
};


struct OpCreateGenerator : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_generator;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_generator"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
    }

    OpCreateGenerator(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateGenerator(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateGenerator(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateGenerator decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_create_generator;
        Metadata(const OpCreateGenerator&) { }

        WriteBarrier<JSCell> m_cachedCallee;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_metadataID;
};


struct OpJneqPtr : public Instruction {
    static constexpr OpcodeID opcodeID = op_jneq_ptr;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value, VirtualRegister specialPointer, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value, specialPointer, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value, VirtualRegister specialPointer, BoundLabel targetLabel)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, value, specialPointer, targetLabel, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister value, VirtualRegister specialPointer, BoundLabel targetLabel)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, value, specialPointer, targetLabel, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value, VirtualRegister specialPointer, BoundLabel targetLabel, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value, specialPointer, targetLabel, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, VirtualRegister specialPointer, BoundLabel targetLabel)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value, specialPointer, targetLabel, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value, specialPointer, targetLabel, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value, specialPointer, targetLabel, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, VirtualRegister& specialPointer, BoundLabel& targetLabel, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(specialPointer)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, VirtualRegister specialPointer, BoundLabel targetLabel, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value, specialPointer, targetLabel, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(specialPointer));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jneq_ptr"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
        dumper->dumpOperand("specialPointer", m_specialPointer, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJneqPtr(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_specialPointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJneqPtr(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_specialPointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJneqPtr(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_specialPointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJneqPtr decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSpecialPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSpecialPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSpecialPointer<OpcodeSize::Wide16>(value, func);
        else
            setSpecialPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSpecialPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_jneq_ptr;
        Metadata(const OpJneqPtr&) { }

        bool m_hasJumped;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_value;
    VirtualRegister m_specialPointer;
    BoundLabel m_targetLabel;
    unsigned m_metadataID;
};


struct OpProfileType : public Instruction {
    static constexpr OpcodeID opcodeID = op_profile_type;
    static constexpr size_t length = 7;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& targetVirtualRegister, SymbolTableOrScopeDepth& symbolTableOrScopeDepth, ProfileTypeBytecodeFlag& flag, unsigned& identifier, ResolveType& resolveType, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(targetVirtualRegister)
            && Fits<SymbolTableOrScopeDepth, __size>::check(symbolTableOrScopeDepth)
            && Fits<ProfileTypeBytecodeFlag, __size>::check(flag)
            && Fits<unsigned, __size>::check(identifier)
            && Fits<ResolveType, __size>::check(resolveType)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister, SymbolTableOrScopeDepth symbolTableOrScopeDepth, ProfileTypeBytecodeFlag flag, unsigned identifier, ResolveType resolveType, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(targetVirtualRegister));
            gen->write(Fits<SymbolTableOrScopeDepth, __size>::convert(symbolTableOrScopeDepth));
            gen->write(Fits<ProfileTypeBytecodeFlag, __size>::convert(flag));
            gen->write(Fits<unsigned, __size>::convert(identifier));
            gen->write(Fits<ResolveType, __size>::convert(resolveType));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**profile_type"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("targetVirtualRegister", m_targetVirtualRegister, true);
        dumper->dumpOperand("symbolTableOrScopeDepth", m_symbolTableOrScopeDepth, false);
        dumper->dumpOperand("flag", m_flag, false);
        dumper->dumpOperand("identifier", m_identifier, false);
        dumper->dumpOperand("resolveType", m_resolveType, false);
    }

    OpProfileType(const uint8_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[1]))
        , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Narrow>::convert(stream[2]))
        , m_identifier(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpProfileType(const uint16_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide16>::convert(stream[1]))
        , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Wide16>::convert(stream[2]))
        , m_identifier(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpProfileType(const uint32_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide32>::convert(stream[1]))
        , m_flag(Fits<ProfileTypeBytecodeFlag, OpcodeSize::Wide32>::convert(stream[2]))
        , m_identifier(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpProfileType decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTargetVirtualRegister(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetVirtualRegister<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetVirtualRegister<OpcodeSize::Wide16>(value, func);
        else
            setTargetVirtualRegister<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetVirtualRegister(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSymbolTableOrScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSymbolTableOrScopeDepth<OpcodeSize::Wide16>(value, func);
        else
            setSymbolTableOrScopeDepth<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
    {
        if (!Fits<SymbolTableOrScopeDepth, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value);
    }

    template<typename Functor>
    void setFlag(ProfileTypeBytecodeFlag value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFlag<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFlag<OpcodeSize::Wide16>(value, func);
        else
            setFlag<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFlag(ProfileTypeBytecodeFlag value, Functor func)
    {
        if (!Fits<ProfileTypeBytecodeFlag, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ProfileTypeBytecodeFlag, size>::convert(value);
    }

    template<typename Functor>
    void setIdentifier(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIdentifier<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIdentifier<OpcodeSize::Wide16>(value, func);
        else
            setIdentifier<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIdentifier(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setResolveType(ResolveType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setResolveType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setResolveType<OpcodeSize::Wide16>(value, func);
        else
            setResolveType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setResolveType(ResolveType value, Functor func)
    {
        if (!Fits<ResolveType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ResolveType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_profile_type;
        Metadata(const OpProfileType&) { }

        TypeLocation* m_typeLocation;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_targetVirtualRegister;
    SymbolTableOrScopeDepth m_symbolTableOrScopeDepth;
    ProfileTypeBytecodeFlag m_flag;
    unsigned m_identifier;
    ResolveType m_resolveType;
    unsigned m_metadataID;
};


struct OpProfileControlFlow : public Instruction {
    static constexpr OpcodeID opcodeID = op_profile_control_flow;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, int textOffset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, textOffset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, int textOffset)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, textOffset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, int textOffset)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, textOffset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, int textOffset, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, textOffset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, int textOffset)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, textOffset, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, textOffset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, textOffset, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, int& textOffset, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<int, __size>::check(textOffset)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, int textOffset, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, textOffset, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<int, __size>::convert(textOffset));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**profile_control_flow"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("textOffset", m_textOffset, true);
    }

    OpProfileControlFlow(const uint8_t* stream)
        : m_textOffset(Fits<int, OpcodeSize::Narrow>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpProfileControlFlow(const uint16_t* stream)
        : m_textOffset(Fits<int, OpcodeSize::Wide16>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpProfileControlFlow(const uint32_t* stream)
        : m_textOffset(Fits<int, OpcodeSize::Wide32>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpProfileControlFlow decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTextOffset(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTextOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTextOffset<OpcodeSize::Wide16>(value, func);
        else
            setTextOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTextOffset(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_profile_control_flow;
        Metadata(const OpProfileControlFlow&) { }

        BasicBlockLocation* m_basicBlockLocation;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    int m_textOffset;
    unsigned m_metadataID;
};


struct OpBitor : public Instruction {
    static constexpr OpcodeID opcodeID = op_bitor;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpBitor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpBitor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpBitor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpBitor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_bitor;
        Metadata(const OpBitor&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    unsigned m_metadataID;
};


struct OpHasEnumerableIndexedProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_enumerable_indexed_property;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_enumerable_indexed_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpHasEnumerableIndexedProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpHasEnumerableIndexedProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpHasEnumerableIndexedProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpHasEnumerableIndexedProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_has_enumerable_indexed_property;
        Metadata(const OpHasEnumerableIndexedProperty&) { }

        ArrayProfile m_arrayProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_metadataID;
};


struct OpBitxor : public Instruction {
    static constexpr OpcodeID opcodeID = op_bitxor;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitxor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpBitxor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpBitxor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpBitxor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpBitxor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_bitxor;
        Metadata(const OpBitxor&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    unsigned m_metadataID;
};


struct OpLshift : public Instruction {
    static constexpr OpcodeID opcodeID = op_lshift;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**lshift"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpLshift(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpLshift(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpLshift(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpLshift decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_lshift;
        Metadata(const OpLshift&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    unsigned m_metadataID;
};


struct OpRshift : public Instruction {
    static constexpr OpcodeID opcodeID = op_rshift;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**rshift"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpRshift(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpRshift(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpRshift(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpRshift decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_rshift;
        Metadata(const OpRshift&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    unsigned m_metadataID;
};


struct OpBitnot : public Instruction {
    static constexpr OpcodeID opcodeID = op_bitnot;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, operand, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, operand, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitnot"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpBitnot(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpBitnot(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpBitnot(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpBitnot decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_bitnot;
        Metadata(const OpBitnot&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_metadataID;
};


struct OpGetDirectPname : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_direct_pname;
    static constexpr size_t length = 7;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property, index, enumerator);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, index, enumerator, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, index, enumerator, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, index, enumerator, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, index, enumerator, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, VirtualRegister& index, VirtualRegister& enumerator, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(index)
            && Fits<VirtualRegister, __size>::check(enumerator)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister index, VirtualRegister enumerator, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, index, enumerator, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(index));
            gen->write(Fits<VirtualRegister, __size>::convert(enumerator));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_direct_pname"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("index", m_index, false);
        dumper->dumpOperand("enumerator", m_enumerator, false);
    }

    OpGetDirectPname(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetDirectPname(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetDirectPname(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetDirectPname decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide16>(value, func);
        else
            setEnumerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_direct_pname;
        Metadata(const OpGetDirectPname&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_index;
    VirtualRegister m_enumerator;
    unsigned m_metadataID;
};


struct OpNewArray : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, argv, argc, recommendedIndexingType);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& argv, unsigned& argc, IndexingType& recommendedIndexingType, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(argv)
            && Fits<unsigned, __size>::check(argc)
            && Fits<IndexingType, __size>::check(recommendedIndexingType)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, IndexingType recommendedIndexingType, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, argv, argc, recommendedIndexingType, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(argv));
            gen->write(Fits<unsigned, __size>::convert(argc));
            gen->write(Fits<IndexingType, __size>::convert(recommendedIndexingType));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("argv", m_argv, false);
        dumper->dumpOperand("argc", m_argc, false);
        dumper->dumpOperand("recommendedIndexingType", m_recommendedIndexingType, false);
    }

    OpNewArray(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewArray(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewArray(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewArray decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide16>(value, func);
        else
            setArgv<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgv(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide16>(value, func);
        else
            setArgc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setRecommendedIndexingType(IndexingType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRecommendedIndexingType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRecommendedIndexingType<OpcodeSize::Wide16>(value, func);
        else
            setRecommendedIndexingType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRecommendedIndexingType(IndexingType value, Functor func)
    {
        if (!Fits<IndexingType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<IndexingType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_new_array;
        Metadata(const OpNewArray&) { }

        ArrayAllocationProfile m_arrayAllocationProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_argv;
    unsigned m_argc;
    IndexingType m_recommendedIndexingType;
    unsigned m_metadataID;
};


struct OpPutById : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_id;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, value, flags);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, base, property, value, flags, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, base, property, value, flags, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, value, flags, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, value, flags, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, value, flags, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, value, flags, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, VirtualRegister& value, PutByIdFlags& flags, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<PutByIdFlags, __size>::check(flags)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, value, flags, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<PutByIdFlags, __size>::convert(flags));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("flags", m_flags, false);
    }

    OpPutById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_flags(Fits<PutByIdFlags, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_flags(Fits<PutByIdFlags, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_flags(Fits<PutByIdFlags, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFlags(PutByIdFlags value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFlags<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFlags<OpcodeSize::Wide16>(value, func);
        else
            setFlags<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFlags(PutByIdFlags value, Functor func)
    {
        if (!Fits<PutByIdFlags, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<PutByIdFlags, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_put_by_id;
        Metadata(const OpPutById&) { }

        StructureID m_oldStructureID;
        unsigned m_offset;
        StructureID m_newStructureID;
        WriteBarrierBase<StructureChain> m_structureChain;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_base;
    unsigned m_property;
    VirtualRegister m_value;
    PutByIdFlags m_flags;
    unsigned m_metadataID;
};


struct OpInByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_in_by_val;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**in_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpInByVal(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpInByVal(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpInByVal(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpInByVal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_in_by_val;
        Metadata(const OpInByVal&) { }

        ArrayProfile m_arrayProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_metadataID;
};


struct OpNewArrayBuffer : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array_buffer;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, immutableButterfly, recommendedIndexingType);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& immutableButterfly, IndexingType& recommendedIndexingType, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(immutableButterfly)
            && Fits<IndexingType, __size>::check(recommendedIndexingType)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(immutableButterfly));
            gen->write(Fits<IndexingType, __size>::convert(recommendedIndexingType));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array_buffer"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("immutableButterfly", m_immutableButterfly, false);
        dumper->dumpOperand("recommendedIndexingType", m_recommendedIndexingType, false);
    }

    OpNewArrayBuffer(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewArrayBuffer(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewArrayBuffer(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_immutableButterfly(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewArrayBuffer decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setImmutableButterfly(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setImmutableButterfly<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setImmutableButterfly<OpcodeSize::Wide16>(value, func);
        else
            setImmutableButterfly<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setImmutableButterfly(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRecommendedIndexingType(IndexingType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRecommendedIndexingType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRecommendedIndexingType<OpcodeSize::Wide16>(value, func);
        else
            setRecommendedIndexingType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRecommendedIndexingType(IndexingType value, Functor func)
    {
        if (!Fits<IndexingType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<IndexingType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_new_array_buffer;
        Metadata(const OpNewArrayBuffer&) { }

        ArrayAllocationProfile m_arrayAllocationProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_immutableButterfly;
    IndexingType m_recommendedIndexingType;
    unsigned m_metadataID;
};


struct OpGetById : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_id;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpGetById(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetById(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetById(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_by_id;
        Metadata(const OpGetById&) { }

        GetByIdModeMetadata m_modeMetadata;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
    unsigned m_metadataID;
};


struct OpGetInternalField : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_internal_field;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, index);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned index)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, index, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned index)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, index, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned index, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, index, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned index)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, index, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, index, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, index, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& index, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(index)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned index, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, index, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(index));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_internal_field"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("index", m_index, false);
    }

    OpGetInternalField(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetInternalField(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetInternalField(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetInternalField decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_internal_field;
        Metadata(const OpGetInternalField&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_index;
    unsigned m_metadataID;
};


struct OpToThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_this;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, srcDst, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, ECMAMode ecmaMode)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, srcDst, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister srcDst, ECMAMode ecmaMode)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, srcDst, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, ECMAMode ecmaMode, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, srcDst, ecmaMode, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst, ECMAMode ecmaMode)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, srcDst, ecmaMode, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, srcDst, ecmaMode, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, srcDst, ecmaMode, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst, ECMAMode& ecmaMode, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(srcDst)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, ECMAMode ecmaMode, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, srcDst, ecmaMode, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(srcDst));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("srcDst", m_srcDst, true);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpToThis(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToThis(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToThis(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToThis decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide16>(value, func);
        else
            setSrcDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_to_this;
        Metadata(const OpToThis&) { }

        StructureID m_cachedStructureID;
        ToThisStatus m_toThisStatus;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_srcDst;
    ECMAMode m_ecmaMode;
    unsigned m_metadataID;
};


struct OpPutByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_val;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, value, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, base, property, value, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, base, property, value, ecmaMode, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, value, ecmaMode, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, value, ecmaMode, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, value, ecmaMode, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, value, ecmaMode, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, ECMAMode& ecmaMode, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, value, ecmaMode, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpPutByVal(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutByVal(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutByVal(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutByVal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_put_by_val;
        Metadata(const OpPutByVal&) { }

        ArrayProfile m_arrayProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_value;
    ECMAMode m_ecmaMode;
    unsigned m_metadataID;
};


struct OpCreatePromise : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_promise;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, bool isInternalPromise)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee, isInternalPromise);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, bool isInternalPromise)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, isInternalPromise, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, bool isInternalPromise)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, isInternalPromise, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, bool isInternalPromise, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, isInternalPromise, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, bool isInternalPromise)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, isInternalPromise, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, isInternalPromise, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, isInternalPromise, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, bool& isInternalPromise, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<bool, __size>::check(isInternalPromise)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, bool isInternalPromise, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, isInternalPromise, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<bool, __size>::convert(isInternalPromise));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_promise"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
        dumper->dumpOperand("isInternalPromise", m_isInternalPromise, false);
    }

    OpCreatePromise(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_isInternalPromise(Fits<bool, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreatePromise(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_isInternalPromise(Fits<bool, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreatePromise(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_isInternalPromise(Fits<bool, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreatePromise decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIsInternalPromise(bool value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIsInternalPromise<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIsInternalPromise<OpcodeSize::Wide16>(value, func);
        else
            setIsInternalPromise<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIsInternalPromise(bool value, Functor func)
    {
        if (!Fits<bool, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<bool, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_create_promise;
        Metadata(const OpCreatePromise&) { }

        WriteBarrier<JSCell> m_cachedCallee;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    bool m_isInternalPromise;
    unsigned m_metadataID;
};


struct OpCreateAsyncGenerator : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_async_generator;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, callee);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, callee, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, callee, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, callee, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, callee, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, callee, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, callee, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& callee, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(callee)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, callee, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(callee));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_async_generator"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("callee", m_callee, false);
    }

    OpCreateAsyncGenerator(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateAsyncGenerator(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateAsyncGenerator(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_callee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateAsyncGenerator decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCallee<OpcodeSize::Wide16>(value, func);
        else
            setCallee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_create_async_generator;
        Metadata(const OpCreateAsyncGenerator&) { }

        WriteBarrier<JSCell> m_cachedCallee;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_callee;
    unsigned m_metadataID;
};


struct OpGetByValWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_val_with_this;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, thisValue, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, base, thisValue, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, base, thisValue, property, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, thisValue, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, thisValue, property, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& thisValue, VirtualRegister& property, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, thisValue, property, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_val_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpGetByValWithThis(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetByValWithThis(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetByValWithThis(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetByValWithThis decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_by_val_with_this;
        Metadata(const OpGetByValWithThis&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_thisValue;
    VirtualRegister m_property;
    unsigned m_metadataID;
};


struct OpResolveScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_resolve_scope;
    static constexpr size_t length = 7;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, var, resolveType, localScopeDepth);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& var, ResolveType& resolveType, unsigned& localScopeDepth, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(var)
            && Fits<ResolveType, __size>::check(resolveType)
            && Fits<unsigned, __size>::check(localScopeDepth)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(var));
            gen->write(Fits<ResolveType, __size>::convert(resolveType));
            gen->write(Fits<unsigned, __size>::convert(localScopeDepth));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**resolve_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("var", m_var, false);
        dumper->dumpOperand("resolveType", m_resolveType, false);
        dumper->dumpOperand("localScopeDepth", m_localScopeDepth, false);
    }

    OpResolveScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[3]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpResolveScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Wide16>::convert(stream[3]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpResolveScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Wide32>::convert(stream[3]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpResolveScope decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setVar<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setVar<OpcodeSize::Wide16>(value, func);
        else
            setVar<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setResolveType(ResolveType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setResolveType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setResolveType<OpcodeSize::Wide16>(value, func);
        else
            setResolveType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setResolveType(ResolveType value, Functor func)
    {
        if (!Fits<ResolveType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ResolveType, size>::convert(value);
    }

    template<typename Functor>
    void setLocalScopeDepth(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLocalScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLocalScopeDepth<OpcodeSize::Wide16>(value, func);
        else
            setLocalScopeDepth<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLocalScopeDepth(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_resolve_scope;
        Metadata(const OpResolveScope&) { }

        ResolveType m_resolveType;
        union {
            unsigned m_localScopeDepth;
            unsigned m_globalLexicalBindingEpoch;
        };
        union {
            WriteBarrierBase<JSCell> m_lexicalEnvironment;
            WriteBarrierBase<SymbolTable> m_symbolTable;
            WriteBarrierBase<JSScope> m_constantScope;
            WriteBarrierBase<JSGlobalLexicalEnvironment> m_globalLexicalEnvironment;
            WriteBarrierBase<JSGlobalObject> m_globalObject;
        };
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_var;
    ResolveType m_resolveType;
    unsigned m_localScopeDepth;
    unsigned m_metadataID;
};


struct OpGetFromScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_from_scope;
    static constexpr size_t length = 8;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& var, GetPutInfo& getPutInfo, unsigned& localScopeDepth, unsigned& offset, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(var)
            && Fits<GetPutInfo, __size>::check(getPutInfo)
            && Fits<unsigned, __size>::check(localScopeDepth)
            && Fits<unsigned, __size>::check(offset)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(var));
            gen->write(Fits<GetPutInfo, __size>::convert(getPutInfo));
            gen->write(Fits<unsigned, __size>::convert(localScopeDepth));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_from_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("var", m_var, false);
        dumper->dumpOperand("getPutInfo", m_getPutInfo, false);
        dumper->dumpOperand("localScopeDepth", m_localScopeDepth, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    OpGetFromScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[3]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetFromScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide16>::convert(stream[3]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetFromScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide32>::convert(stream[3]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetFromScope decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setVar<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setVar<OpcodeSize::Wide16>(value, func);
        else
            setVar<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setGetPutInfo(GetPutInfo value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setGetPutInfo<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setGetPutInfo<OpcodeSize::Wide16>(value, func);
        else
            setGetPutInfo<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGetPutInfo(GetPutInfo value, Functor func)
    {
        if (!Fits<GetPutInfo, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<GetPutInfo, size>::convert(value);
    }

    template<typename Functor>
    void setLocalScopeDepth(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLocalScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLocalScopeDepth<OpcodeSize::Wide16>(value, func);
        else
            setLocalScopeDepth<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLocalScopeDepth(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_from_scope;
        Metadata(const OpGetFromScope& __op)
            : m_getPutInfo(__op.m_getPutInfo)
            , m_operand(__op.m_offset)
        { }

        GetPutInfo m_getPutInfo;
        union {
            WatchpointSet* m_watchpointSet;
            WriteBarrierBase<Structure> m_structure;
        };
        uintptr_t m_operand;
        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_var;
    GetPutInfo m_getPutInfo;
    unsigned m_localScopeDepth;
    unsigned m_offset;
    unsigned m_metadataID;
};


struct OpPutToScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_to_scope;
    static constexpr size_t length = 8;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& scope, unsigned& var, VirtualRegister& value, GetPutInfo& getPutInfo, SymbolTableOrScopeDepth& symbolTableOrScopeDepth, unsigned& offset, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(var)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<GetPutInfo, __size>::check(getPutInfo)
            && Fits<SymbolTableOrScopeDepth, __size>::check(symbolTableOrScopeDepth)
            && Fits<unsigned, __size>::check(offset)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(var));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<GetPutInfo, __size>::convert(getPutInfo));
            gen->write(Fits<SymbolTableOrScopeDepth, __size>::convert(symbolTableOrScopeDepth));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_to_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("scope", m_scope, true);
        dumper->dumpOperand("var", m_var, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("getPutInfo", m_getPutInfo, false);
        dumper->dumpOperand("symbolTableOrScopeDepth", m_symbolTableOrScopeDepth, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    OpPutToScope(const uint8_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[3]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[4]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutToScope(const uint16_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide16>::convert(stream[3]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide16>::convert(stream[4]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutToScope(const uint32_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide32>::convert(stream[3]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide32>::convert(stream[4]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutToScope decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setVar<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setVar<OpcodeSize::Wide16>(value, func);
        else
            setVar<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setGetPutInfo(GetPutInfo value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setGetPutInfo<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setGetPutInfo<OpcodeSize::Wide16>(value, func);
        else
            setGetPutInfo<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGetPutInfo(GetPutInfo value, Functor func)
    {
        if (!Fits<GetPutInfo, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<GetPutInfo, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSymbolTableOrScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSymbolTableOrScopeDepth<OpcodeSize::Wide16>(value, func);
        else
            setSymbolTableOrScopeDepth<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
    {
        if (!Fits<SymbolTableOrScopeDepth, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 5 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_put_to_scope;
        Metadata(const OpPutToScope& __op)
            : m_getPutInfo(__op.m_getPutInfo)
            , m_operand(__op.m_offset)
        { }

        GetPutInfo m_getPutInfo;
        union {
            WriteBarrierBase<Structure> m_structure;
            WatchpointSet* m_watchpointSet;
        };
        uintptr_t m_operand;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_scope;
    unsigned m_var;
    VirtualRegister m_value;
    GetPutInfo m_getPutInfo;
    SymbolTableOrScopeDepth m_symbolTableOrScopeDepth;
    unsigned m_offset;
    unsigned m_metadataID;
};


struct OpGetFromArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_from_arguments;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, arguments, index);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, arguments, index, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, arguments, index, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, arguments, index, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, arguments, index, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, arguments, index, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, arguments, index, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& arguments, unsigned& index, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(arguments)
            && Fits<unsigned, __size>::check(index)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arguments, unsigned index, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, arguments, index, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(arguments));
            gen->write(Fits<unsigned, __size>::convert(index));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_from_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("arguments", m_arguments, false);
        dumper->dumpOperand("index", m_index, false);
    }

    OpGetFromArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetFromArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetFromArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetFromArguments decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide16>(value, func);
        else
            setArguments<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_get_from_arguments;
        Metadata(const OpGetFromArguments&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_arguments;
    unsigned m_index;
    unsigned m_metadataID;
};


struct OpSub : public Instruction {
    static constexpr OpcodeID opcodeID = op_sub;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, OperandTypes& operandTypes, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<OperandTypes, __size>::check(operandTypes)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, operandTypes, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<OperandTypes, __size>::convert(operandTypes));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("operandTypes", m_operandTypes, false);
    }

    OpSub(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSub(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSub(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_operandTypes(Fits<OperandTypes, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSub decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperandTypes<OpcodeSize::Wide16>(value, func);
        else
            setOperandTypes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (!Fits<OperandTypes, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_sub;
        Metadata(const OpSub&) { }

        BinaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    OperandTypes m_operandTypes;
    unsigned m_metadataID;
};


struct OpBitand : public Instruction {
    static constexpr OpcodeID opcodeID = op_bitand;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitand"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpBitand(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpBitand(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpBitand(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpBitand decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_bitand;
        Metadata(const OpBitand&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    unsigned m_metadataID;
};


struct OpInc : public Instruction {
    static constexpr OpcodeID opcodeID = op_inc;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, srcDst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, srcDst, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, srcDst, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, srcDst, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, srcDst, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, srcDst, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, srcDst, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(srcDst)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, srcDst, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(srcDst));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**inc"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("srcDst", m_srcDst, true);
    }

    OpInc(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpInc(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpInc(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpInc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide16>(value, func);
        else
            setSrcDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_inc;
        Metadata(const OpInc&) { }

        UnaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_srcDst;
    unsigned m_metadataID;
};


struct OpDec : public Instruction {
    static constexpr OpcodeID opcodeID = op_dec;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, srcDst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, srcDst, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, srcDst, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, srcDst, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, srcDst, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, srcDst, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, srcDst, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(srcDst)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, srcDst, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(srcDst));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**dec"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("srcDst", m_srcDst, true);
    }

    OpDec(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDec(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDec(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDec decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide16>(value, func);
        else
            setSrcDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_dec;
        Metadata(const OpDec&) { }

        UnaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_srcDst;
    unsigned m_metadataID;
};


struct OpToObject : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_object;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand, message);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, operand, message, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, operand, message, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand, message, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand, message, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand, message, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand, message, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned& message, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && Fits<unsigned, __size>::check(message)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned message, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand, message, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            gen->write(Fits<unsigned, __size>::convert(message));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
        dumper->dumpOperand("message", m_message, false);
    }

    OpToObject(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_message(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToObject(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_message(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToObject(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_message(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToObject decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setMessage(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setMessage<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setMessage<OpcodeSize::Wide16>(value, func);
        else
            setMessage<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setMessage(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_to_object;
        Metadata(const OpToObject&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_message;
    unsigned m_metadataID;
};


struct OpCatch : public Instruction {
    static constexpr OpcodeID opcodeID = op_catch;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, exception, thrownValue);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, exception, thrownValue, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, exception, thrownValue, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, exception, thrownValue, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, exception, thrownValue, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, exception, thrownValue, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, exception, thrownValue, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& exception, VirtualRegister& thrownValue, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(exception)
            && Fits<VirtualRegister, __size>::check(thrownValue)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, exception, thrownValue, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(exception));
            gen->write(Fits<VirtualRegister, __size>::convert(thrownValue));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**catch"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("exception", m_exception, true);
        dumper->dumpOperand("thrownValue", m_thrownValue, false);
    }

    OpCatch(const uint8_t* stream)
        : m_exception(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCatch(const uint16_t* stream)
        : m_exception(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCatch(const uint32_t* stream)
        : m_exception(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCatch decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setException(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setException<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setException<OpcodeSize::Wide16>(value, func);
        else
            setException<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setException(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThrownValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThrownValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThrownValue<OpcodeSize::Wide16>(value, func);
        else
            setThrownValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThrownValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_catch;
        Metadata(const OpCatch&) { }

        ValueProfileAndVirtualRegisterBuffer* m_buffer;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_exception;
    VirtualRegister m_thrownValue;
    unsigned m_metadataID;
};


struct OpToNumber : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_number;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, operand, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, operand, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_number"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpToNumber(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToNumber(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToNumber(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToNumber decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_to_number;
        Metadata(const OpToNumber&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_metadataID;
};


struct OpToNumeric : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_numeric;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, operand, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, operand, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_numeric"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpToNumeric(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToNumeric(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToNumeric(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToNumeric decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_to_numeric;
        Metadata(const OpToNumeric&) { }

        ValueProfile m_profile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_metadataID;
};


struct OpNegate : public Instruction {
    static constexpr OpcodeID opcodeID = op_negate;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, ResultType resultType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand, resultType);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, ResultType resultType)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<__size, BytecodeGenerator, shouldAssert>(gen, dst, operand, resultType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, ResultType resultType)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<__size, BytecodeGenerator>(gen, dst, operand, resultType, __metadataID);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, ResultType resultType, unsigned __metadataID)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand, resultType, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, ResultType resultType)
    {
        
        auto __metadataID = gen->addMetadataFor(opcodeID);
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand, resultType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand, resultType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand, resultType, __metadataID);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, ResultType& resultType, unsigned __metadataID)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && Fits<ResultType, __size>::check(resultType)
            && Fits<unsigned, __size>::check(__metadataID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, ResultType resultType, unsigned __metadataID)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand, resultType, __metadataID)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            gen->write(Fits<ResultType, __size>::convert(resultType));
            gen->write(Fits<unsigned, __size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**negate"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
        dumper->dumpOperand("resultType", m_resultType, false);
    }

    OpNegate(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_resultType(Fits<ResultType, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNegate(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_resultType(Fits<ResultType, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNegate(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_resultType(Fits<ResultType, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNegate decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setResultType(ResultType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setResultType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setResultType<OpcodeSize::Wide16>(value, func);
        else
            setResultType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setResultType(ResultType value, Functor func)
    {
        if (!Fits<ResultType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ResultType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        static constexpr OpcodeID opcodeID = op_negate;
        Metadata(const OpNegate&) { }

        UnaryArithProfile m_arithProfile;
    };

    Metadata& metadata(CodeBlock* codeBlock) const
    {
        return codeBlock->metadata<Metadata>(opcodeID, m_metadataID);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    ResultType m_resultType;
    unsigned m_metadataID;
};


struct OpPutSetterByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_setter_by_val;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, attributes, accessor);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, attributes, accessor);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, unsigned& attributes, VirtualRegister& accessor)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(attributes)
            && Fits<VirtualRegister, __size>::check(accessor)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, attributes, accessor)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(attributes));
            gen->write(Fits<VirtualRegister, __size>::convert(accessor));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_setter_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("attributes", m_attributes, false);
        dumper->dumpOperand("accessor", m_accessor, false);
    }

    OpPutSetterByVal(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutSetterByVal(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutSetterByVal(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutSetterByVal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide16>(value, func);
        else
            setAccessor<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_attributes;
    VirtualRegister m_accessor;
};


struct OpDefineDataProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_define_data_property;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, value, attributes);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, value, attributes);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, value, attributes))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, value, attributes))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, value, attributes);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& value, VirtualRegister& attributes)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(attributes)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, value, attributes)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(attributes));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**define_data_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("attributes", m_attributes, false);
    }

    OpDefineDataProperty(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDefineDataProperty(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDefineDataProperty(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDefineDataProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_value;
    VirtualRegister m_attributes;
};


struct OpDefineAccessorProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_define_accessor_property;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, getter, setter, attributes);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, getter, setter, attributes);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, getter, setter, attributes))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, getter, setter, attributes))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, getter, setter, attributes);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, VirtualRegister& getter, VirtualRegister& setter, VirtualRegister& attributes)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(getter)
            && Fits<VirtualRegister, __size>::check(setter)
            && Fits<VirtualRegister, __size>::check(attributes)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, getter, setter, attributes)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(getter));
            gen->write(Fits<VirtualRegister, __size>::convert(setter));
            gen->write(Fits<VirtualRegister, __size>::convert(attributes));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**define_accessor_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("getter", m_getter, false);
        dumper->dumpOperand("setter", m_setter, false);
        dumper->dumpOperand("attributes", m_attributes, false);
    }

    OpDefineAccessorProperty(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDefineAccessorProperty(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDefineAccessorProperty(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDefineAccessorProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setGetter(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setGetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setGetter<OpcodeSize::Wide16>(value, func);
        else
            setGetter<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGetter(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSetter(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSetter<OpcodeSize::Wide16>(value, func);
        else
            setSetter<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSetter(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_getter;
    VirtualRegister m_setter;
    VirtualRegister m_attributes;
};


struct OpJmp : public Instruction {
    static constexpr OpcodeID opcodeID = op_jmp;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jmp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("targetLabel", m_targetLabel, true);
    }

    OpJmp(const uint8_t* stream)
        : m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJmp(const uint16_t* stream)
        : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJmp(const uint32_t* stream)
        : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJmp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    BoundLabel m_targetLabel;
};


struct OpJtrue : public Instruction {
    static constexpr OpcodeID opcodeID = op_jtrue;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, condition, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, condition, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, condition, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& condition, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(condition)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, condition, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(condition));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jtrue"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("condition", m_condition, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJtrue(const uint8_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJtrue(const uint16_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJtrue(const uint32_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJtrue decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCondition<OpcodeSize::Wide16>(value, func);
        else
            setCondition<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_condition;
    BoundLabel m_targetLabel;
};


struct OpJfalse : public Instruction {
    static constexpr OpcodeID opcodeID = op_jfalse;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, condition, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, condition, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, condition, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& condition, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(condition)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, condition, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(condition));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jfalse"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("condition", m_condition, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJfalse(const uint8_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJfalse(const uint16_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJfalse(const uint32_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJfalse decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCondition<OpcodeSize::Wide16>(value, func);
        else
            setCondition<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_condition;
    BoundLabel m_targetLabel;
};


struct OpJeqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_jeq_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jeq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJeqNull(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJeqNull(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJeqNull(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJeqNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_value;
    BoundLabel m_targetLabel;
};


struct OpJneqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_jneq_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jneq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJneqNull(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJneqNull(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJneqNull(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJneqNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_value;
    BoundLabel m_targetLabel;
};


struct OpJundefinedOrNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_jundefined_or_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jundefined_or_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJundefinedOrNull(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJundefinedOrNull(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJundefinedOrNull(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJundefinedOrNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_value;
    BoundLabel m_targetLabel;
};


struct OpJnundefinedOrNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_jnundefined_or_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnundefined_or_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJnundefinedOrNull(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJnundefinedOrNull(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJnundefinedOrNull(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJnundefinedOrNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_value;
    BoundLabel m_targetLabel;
};


struct OpJeq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jeq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jeq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJeq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJeq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJeq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJeq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJstricteq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jstricteq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jstricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJstricteq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJstricteq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJstricteq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJstricteq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJneq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jneq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jneq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJneq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJneq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJneq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJneq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJnstricteq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jnstricteq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnstricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJnstricteq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJnstricteq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJnstricteq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJnstricteq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJless : public Instruction {
    static constexpr OpcodeID opcodeID = op_jless;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jless"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJless(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJless(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJless(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJless decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJlesseq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jlesseq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jlesseq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJlesseq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJlesseq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJlesseq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJlesseq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJgreater : public Instruction {
    static constexpr OpcodeID opcodeID = op_jgreater;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jgreater"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJgreater(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJgreater(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJgreater(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJgreater decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJgreatereq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jgreatereq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jgreatereq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJgreatereq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJgreatereq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJgreatereq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJgreatereq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJnless : public Instruction {
    static constexpr OpcodeID opcodeID = op_jnless;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnless"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJnless(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJnless(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJnless(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJnless decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJnlesseq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jnlesseq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnlesseq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJnlesseq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJnlesseq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJnlesseq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJnlesseq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJngreater : public Instruction {
    static constexpr OpcodeID opcodeID = op_jngreater;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jngreater"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJngreater(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJngreater(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJngreater(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJngreater decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJngreatereq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jngreatereq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jngreatereq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJngreatereq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJngreatereq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJngreatereq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJngreatereq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJbelow : public Instruction {
    static constexpr OpcodeID opcodeID = op_jbelow;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jbelow"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJbelow(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJbelow(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJbelow(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJbelow decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpJbeloweq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jbeloweq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& lhs, VirtualRegister& rhs, BoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && Fits<BoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, lhs, rhs, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            gen->write(Fits<BoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jbeloweq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("lhs", m_lhs, true);
        dumper->dumpOperand("rhs", m_rhs, false);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    OpJbeloweq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpJbeloweq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpJbeloweq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpJbeloweq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
    BoundLabel m_targetLabel;
};


struct OpLoopHint : public Instruction {
    static constexpr OpcodeID opcodeID = op_loop_hint;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**loop_hint"[2 - __sizeShiftAmount]);

    }

    OpLoopHint(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpLoopHint(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpLoopHint(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpLoopHint decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpSwitchImm : public Instruction {
    static constexpr OpcodeID opcodeID = op_switch_imm;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, tableIndex, defaultOffset, scrutinee);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, tableIndex, defaultOffset, scrutinee);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& tableIndex, BoundLabel& defaultOffset, VirtualRegister& scrutinee)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(tableIndex)
            && Fits<BoundLabel, __size>::check(defaultOffset)
            && Fits<VirtualRegister, __size>::check(scrutinee)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, tableIndex, defaultOffset, scrutinee)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            gen->write(Fits<BoundLabel, __size>::convert(defaultOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(scrutinee));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch_imm"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("tableIndex", m_tableIndex, true);
        dumper->dumpOperand("defaultOffset", m_defaultOffset, false);
        dumper->dumpOperand("scrutinee", m_scrutinee, false);
    }

    OpSwitchImm(const uint8_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSwitchImm(const uint16_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSwitchImm(const uint32_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSwitchImm decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDefaultOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDefaultOffset<OpcodeSize::Wide16>(value, func);
        else
            setDefaultOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide16>(value, func);
        else
            setScrutinee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_tableIndex;
    BoundLabel m_defaultOffset;
    VirtualRegister m_scrutinee;
};


struct OpSwitchChar : public Instruction {
    static constexpr OpcodeID opcodeID = op_switch_char;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, tableIndex, defaultOffset, scrutinee);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, tableIndex, defaultOffset, scrutinee);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& tableIndex, BoundLabel& defaultOffset, VirtualRegister& scrutinee)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(tableIndex)
            && Fits<BoundLabel, __size>::check(defaultOffset)
            && Fits<VirtualRegister, __size>::check(scrutinee)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, tableIndex, defaultOffset, scrutinee)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            gen->write(Fits<BoundLabel, __size>::convert(defaultOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(scrutinee));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch_char"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("tableIndex", m_tableIndex, true);
        dumper->dumpOperand("defaultOffset", m_defaultOffset, false);
        dumper->dumpOperand("scrutinee", m_scrutinee, false);
    }

    OpSwitchChar(const uint8_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSwitchChar(const uint16_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSwitchChar(const uint32_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSwitchChar decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDefaultOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDefaultOffset<OpcodeSize::Wide16>(value, func);
        else
            setDefaultOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide16>(value, func);
        else
            setScrutinee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_tableIndex;
    BoundLabel m_defaultOffset;
    VirtualRegister m_scrutinee;
};


struct OpSwitchString : public Instruction {
    static constexpr OpcodeID opcodeID = op_switch_string;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, tableIndex, defaultOffset, scrutinee);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, tableIndex, defaultOffset, scrutinee);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& tableIndex, BoundLabel& defaultOffset, VirtualRegister& scrutinee)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(tableIndex)
            && Fits<BoundLabel, __size>::check(defaultOffset)
            && Fits<VirtualRegister, __size>::check(scrutinee)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, tableIndex, defaultOffset, scrutinee)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            gen->write(Fits<BoundLabel, __size>::convert(defaultOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(scrutinee));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch_string"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("tableIndex", m_tableIndex, true);
        dumper->dumpOperand("defaultOffset", m_defaultOffset, false);
        dumper->dumpOperand("scrutinee", m_scrutinee, false);
    }

    OpSwitchString(const uint8_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSwitchString(const uint16_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSwitchString(const uint32_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSwitchString decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDefaultOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDefaultOffset<OpcodeSize::Wide16>(value, func);
        else
            setDefaultOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (!Fits<BoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide16>(value, func);
        else
            setScrutinee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_tableIndex;
    BoundLabel m_defaultOffset;
    VirtualRegister m_scrutinee;
};


struct OpNewFunc : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_func;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewFunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewFuncExp : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_func_exp;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewFuncExp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewGeneratorFunc : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_generator_func;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_generator_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewGeneratorFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewGeneratorFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewGeneratorFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewGeneratorFunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewGeneratorFuncExp : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_generator_func_exp;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_generator_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewGeneratorFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewGeneratorFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewGeneratorFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewGeneratorFuncExp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewAsyncFunc : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_async_func;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewAsyncFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewAsyncFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewAsyncFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewAsyncFunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewAsyncFuncExp : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_async_func_exp;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewAsyncFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewAsyncFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewAsyncFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewAsyncFuncExp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewAsyncGeneratorFunc : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_async_generator_func;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_generator_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewAsyncGeneratorFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewAsyncGeneratorFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewAsyncGeneratorFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewAsyncGeneratorFunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpNewAsyncGeneratorFuncExp : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_async_generator_func_exp;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, functionDecl);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, functionDecl);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& functionDecl)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(functionDecl)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, functionDecl)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(functionDecl));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_generator_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("functionDecl", m_functionDecl, false);
    }

    OpNewAsyncGeneratorFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewAsyncGeneratorFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewAsyncGeneratorFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewAsyncGeneratorFuncExp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunctionDecl<OpcodeSize::Wide16>(value, func);
        else
            setFunctionDecl<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_functionDecl;
};


struct OpSetFunctionName : public Instruction {
    static constexpr OpcodeID opcodeID = op_set_function_name;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, function, name);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, function, name);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, function, name))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, function, name))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, function, name);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& function, VirtualRegister& name)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(function)
            && Fits<VirtualRegister, __size>::check(name)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, function, name)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(function));
            gen->write(Fits<VirtualRegister, __size>::convert(name));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**set_function_name"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("function", m_function, true);
        dumper->dumpOperand("name", m_name, false);
    }

    OpSetFunctionName(const uint8_t* stream)
        : m_function(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_name(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSetFunctionName(const uint16_t* stream)
        : m_function(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_name(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSetFunctionName(const uint32_t* stream)
        : m_function(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_name(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSetFunctionName decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setFunction(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setFunction<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setFunction<OpcodeSize::Wide16>(value, func);
        else
            setFunction<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunction(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setName(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setName<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setName<OpcodeSize::Wide16>(value, func);
        else
            setName<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setName(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_function;
    VirtualRegister m_name;
};


struct OpRet : public Instruction {
    static constexpr OpcodeID opcodeID = op_ret;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**ret"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
    }

    OpRet(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpRet(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpRet(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpRet decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_value;
};


struct OpStrcat : public Instruction {
    static constexpr OpcodeID opcodeID = op_strcat;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, src, count);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, src, count);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, src, count))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, src, count))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, src, count);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src, int& count)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(src)
            && Fits<int, __size>::check(count)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, src, count)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(src));
            gen->write(Fits<int, __size>::convert(count));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**strcat"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("src", m_src, false);
        dumper->dumpOperand("count", m_count, false);
    }

    OpStrcat(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_count(Fits<int, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpStrcat(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_count(Fits<int, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpStrcat(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_count(Fits<int, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpStrcat decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide16>(value, func);
        else
            setSrc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCount(int value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCount<OpcodeSize::Wide16>(value, func);
        else
            setCount<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCount(int value, Functor func)
    {
        if (!Fits<int, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<int, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
    int m_count;
};


struct OpToPrimitive : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_primitive;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, src);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, src);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, src);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(src)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, src)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(src));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_primitive"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("src", m_src, false);
    }

    OpToPrimitive(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToPrimitive(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToPrimitive(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToPrimitive decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide16>(value, func);
        else
            setSrc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
};


struct OpToPropertyKey : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_property_key;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, src);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, src);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, src);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(src)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, src)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(src));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_property_key"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("src", m_src, false);
    }

    OpToPropertyKey(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToPropertyKey(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToPropertyKey(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToPropertyKey decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide16>(value, func);
        else
            setSrc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
};


struct OpPutToArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_to_arguments;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, arguments, index, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, arguments, index, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, arguments, index, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, arguments, index, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, arguments, index, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& arguments, unsigned& index, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(arguments)
            && Fits<unsigned, __size>::check(index)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, arguments, index, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(arguments));
            gen->write(Fits<unsigned, __size>::convert(index));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_to_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("arguments", m_arguments, true);
        dumper->dumpOperand("index", m_index, false);
        dumper->dumpOperand("value", m_value, false);
    }

    OpPutToArguments(const uint8_t* stream)
        : m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutToArguments(const uint16_t* stream)
        : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutToArguments(const uint32_t* stream)
        : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutToArguments decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArguments<OpcodeSize::Wide16>(value, func);
        else
            setArguments<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_arguments;
    unsigned m_index;
    VirtualRegister m_value;
};


struct OpPushWithScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_push_with_scope;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, currentScope, newScope);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, currentScope, newScope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, currentScope, newScope))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, currentScope, newScope))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, currentScope, newScope);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& currentScope, VirtualRegister& newScope)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(currentScope)
            && Fits<VirtualRegister, __size>::check(newScope)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, currentScope, newScope)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(currentScope));
            gen->write(Fits<VirtualRegister, __size>::convert(newScope));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**push_with_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("currentScope", m_currentScope, false);
        dumper->dumpOperand("newScope", m_newScope, false);
    }

    OpPushWithScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_currentScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_newScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPushWithScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPushWithScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPushWithScope decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCurrentScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setCurrentScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setCurrentScope<OpcodeSize::Wide16>(value, func);
        else
            setCurrentScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCurrentScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNewScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setNewScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setNewScope<OpcodeSize::Wide16>(value, func);
        else
            setNewScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNewScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_currentScope;
    VirtualRegister m_newScope;
};


struct OpCreateLexicalEnvironment : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_lexical_environment;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, symbolTable, initialValue);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, symbolTable, initialValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, symbolTable, initialValue);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, VirtualRegister& symbolTable, VirtualRegister& initialValue)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<VirtualRegister, __size>::check(symbolTable)
            && Fits<VirtualRegister, __size>::check(initialValue)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, symbolTable, initialValue)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<VirtualRegister, __size>::convert(symbolTable));
            gen->write(Fits<VirtualRegister, __size>::convert(initialValue));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_lexical_environment"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("symbolTable", m_symbolTable, false);
        dumper->dumpOperand("initialValue", m_initialValue, false);
    }

    OpCreateLexicalEnvironment(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateLexicalEnvironment(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateLexicalEnvironment(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateLexicalEnvironment decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTable(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSymbolTable<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSymbolTable<OpcodeSize::Wide16>(value, func);
        else
            setSymbolTable<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSymbolTable(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInitialValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setInitialValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setInitialValue<OpcodeSize::Wide16>(value, func);
        else
            setInitialValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setInitialValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    VirtualRegister m_symbolTable;
    VirtualRegister m_initialValue;
};


struct OpCreateGeneratorFrameEnvironment : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_generator_frame_environment;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, symbolTable, initialValue);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, symbolTable, initialValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, symbolTable, initialValue);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, VirtualRegister& symbolTable, VirtualRegister& initialValue)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<VirtualRegister, __size>::check(symbolTable)
            && Fits<VirtualRegister, __size>::check(initialValue)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, symbolTable, initialValue)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<VirtualRegister, __size>::convert(symbolTable));
            gen->write(Fits<VirtualRegister, __size>::convert(initialValue));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_generator_frame_environment"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("symbolTable", m_symbolTable, false);
        dumper->dumpOperand("initialValue", m_initialValue, false);
    }

    OpCreateGeneratorFrameEnvironment(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateGeneratorFrameEnvironment(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateGeneratorFrameEnvironment(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateGeneratorFrameEnvironment decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTable(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSymbolTable<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSymbolTable<OpcodeSize::Wide16>(value, func);
        else
            setSymbolTable<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSymbolTable(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInitialValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setInitialValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setInitialValue<OpcodeSize::Wide16>(value, func);
        else
            setInitialValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setInitialValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    VirtualRegister m_symbolTable;
    VirtualRegister m_initialValue;
};


struct OpGetParentScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_parent_scope;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_parent_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
    }

    OpGetParentScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetParentScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetParentScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetParentScope decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
};


struct OpThrow : public Instruction {
    static constexpr OpcodeID opcodeID = op_throw;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**throw"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
    }

    OpThrow(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpThrow(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpThrow(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpThrow decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_value;
};


struct OpThrowStaticError : public Instruction {
    static constexpr OpcodeID opcodeID = op_throw_static_error;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister message, ErrorTypeWithExtension errorType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, message, errorType);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister message, ErrorTypeWithExtension errorType)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, message, errorType);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister message, ErrorTypeWithExtension errorType)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, message, errorType))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, message, errorType))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, message, errorType);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& message, ErrorTypeWithExtension& errorType)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(message)
            && Fits<ErrorTypeWithExtension, __size>::check(errorType)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister message, ErrorTypeWithExtension errorType)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, message, errorType)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(message));
            gen->write(Fits<ErrorTypeWithExtension, __size>::convert(errorType));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**throw_static_error"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("message", m_message, true);
        dumper->dumpOperand("errorType", m_errorType, false);
    }

    OpThrowStaticError(const uint8_t* stream)
        : m_message(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_errorType(Fits<ErrorTypeWithExtension, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpThrowStaticError(const uint16_t* stream)
        : m_message(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_errorType(Fits<ErrorTypeWithExtension, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpThrowStaticError(const uint32_t* stream)
        : m_message(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_errorType(Fits<ErrorTypeWithExtension, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpThrowStaticError decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setMessage(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setMessage<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setMessage<OpcodeSize::Wide16>(value, func);
        else
            setMessage<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setMessage(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setErrorType(ErrorTypeWithExtension value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setErrorType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setErrorType<OpcodeSize::Wide16>(value, func);
        else
            setErrorType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setErrorType(ErrorTypeWithExtension value, Functor func)
    {
        if (!Fits<ErrorTypeWithExtension, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ErrorTypeWithExtension, size>::convert(value);
    }

    VirtualRegister m_message;
    ErrorTypeWithExtension m_errorType;
};


struct OpDebug : public Instruction {
    static constexpr OpcodeID opcodeID = op_debug;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, debugHookType, hasBreakpoint);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, debugHookType, hasBreakpoint);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, debugHookType, hasBreakpoint))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, debugHookType, hasBreakpoint))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, debugHookType, hasBreakpoint);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, DebugHookType& debugHookType, bool& hasBreakpoint)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<DebugHookType, __size>::check(debugHookType)
            && Fits<bool, __size>::check(hasBreakpoint)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, debugHookType, hasBreakpoint)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<DebugHookType, __size>::convert(debugHookType));
            gen->write(Fits<bool, __size>::convert(hasBreakpoint));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**debug"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("debugHookType", m_debugHookType, true);
        dumper->dumpOperand("hasBreakpoint", m_hasBreakpoint, false);
    }

    OpDebug(const uint8_t* stream)
        : m_debugHookType(Fits<DebugHookType, OpcodeSize::Narrow>::convert(stream[0]))
        , m_hasBreakpoint(Fits<bool, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDebug(const uint16_t* stream)
        : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide16>::convert(stream[0]))
        , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDebug(const uint32_t* stream)
        : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide32>::convert(stream[0]))
        , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDebug decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDebugHookType(DebugHookType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDebugHookType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDebugHookType<OpcodeSize::Wide16>(value, func);
        else
            setDebugHookType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDebugHookType(DebugHookType value, Functor func)
    {
        if (!Fits<DebugHookType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<DebugHookType, size>::convert(value);
    }

    template<typename Functor>
    void setHasBreakpoint(bool value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setHasBreakpoint<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setHasBreakpoint<OpcodeSize::Wide16>(value, func);
        else
            setHasBreakpoint<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setHasBreakpoint(bool value, Functor func)
    {
        if (!Fits<bool, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<bool, size>::convert(value);
    }

    DebugHookType m_debugHookType;
    bool m_hasBreakpoint;
};


struct OpEnd : public Instruction {
    static constexpr OpcodeID opcodeID = op_end;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**end"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("value", m_value, true);
    }

    OpEnd(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpEnd(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpEnd(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpEnd decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_value;
};


struct OpGetEnumerableLength : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_enumerable_length;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_enumerable_length"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
    }

    OpGetEnumerableLength(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetEnumerableLength(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetEnumerableLength(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetEnumerableLength decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
};


struct OpHasEnumerableStructureProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_enumerable_structure_property;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property, enumerator);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, enumerator);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, enumerator);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, VirtualRegister& enumerator)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(enumerator)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, enumerator)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(enumerator));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_enumerable_structure_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("enumerator", m_enumerator, false);
    }

    OpHasEnumerableStructureProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpHasEnumerableStructureProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpHasEnumerableStructureProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpHasEnumerableStructureProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide16>(value, func);
        else
            setEnumerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_enumerator;
};


struct OpHasOwnStructureProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_own_structure_property;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property, enumerator);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, enumerator);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, enumerator);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, VirtualRegister& enumerator)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(enumerator)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, enumerator)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(enumerator));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_own_structure_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("enumerator", m_enumerator, false);
    }

    OpHasOwnStructureProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpHasOwnStructureProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpHasOwnStructureProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpHasOwnStructureProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide16>(value, func);
        else
            setEnumerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_enumerator;
};


struct OpInStructureProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_in_structure_property;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property, enumerator);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, enumerator);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, enumerator);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, VirtualRegister& enumerator)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(enumerator)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, VirtualRegister enumerator)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, enumerator)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(enumerator));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**in_structure_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("enumerator", m_enumerator, false);
    }

    OpInStructureProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpInStructureProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpInStructureProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpInStructureProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide16>(value, func);
        else
            setEnumerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_enumerator;
};


struct OpHasEnumerableProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_enumerable_property;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_enumerable_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpHasEnumerableProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpHasEnumerableProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpHasEnumerableProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpHasEnumerableProperty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
};


struct OpGetPropertyEnumerator : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_property_enumerator;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_property_enumerator"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
    }

    OpGetPropertyEnumerator(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetPropertyEnumerator(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetPropertyEnumerator(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetPropertyEnumerator decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
};


struct OpEnumeratorStructurePname : public Instruction {
    static constexpr OpcodeID opcodeID = op_enumerator_structure_pname;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, enumerator, index);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, enumerator, index);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, enumerator, index);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& enumerator, VirtualRegister& index)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(enumerator)
            && Fits<VirtualRegister, __size>::check(index)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, enumerator, index)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(enumerator));
            gen->write(Fits<VirtualRegister, __size>::convert(index));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enumerator_structure_pname"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("enumerator", m_enumerator, false);
        dumper->dumpOperand("index", m_index, false);
    }

    OpEnumeratorStructurePname(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpEnumeratorStructurePname(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpEnumeratorStructurePname(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpEnumeratorStructurePname decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide16>(value, func);
        else
            setEnumerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_enumerator;
    VirtualRegister m_index;
};


struct OpEnumeratorGenericPname : public Instruction {
    static constexpr OpcodeID opcodeID = op_enumerator_generic_pname;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, enumerator, index);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, enumerator, index);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, enumerator, index);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& enumerator, VirtualRegister& index)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(enumerator)
            && Fits<VirtualRegister, __size>::check(index)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, enumerator, index)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(enumerator));
            gen->write(Fits<VirtualRegister, __size>::convert(index));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enumerator_generic_pname"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("enumerator", m_enumerator, false);
        dumper->dumpOperand("index", m_index, false);
    }

    OpEnumeratorGenericPname(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpEnumeratorGenericPname(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpEnumeratorGenericPname(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpEnumeratorGenericPname decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEnumerator<OpcodeSize::Wide16>(value, func);
        else
            setEnumerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_enumerator;
    VirtualRegister m_index;
};


struct OpToIndexString : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_index_string;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, index);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, index);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, index))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, index))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, index);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& index)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(index)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, index)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(index));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_index_string"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("index", m_index, false);
    }

    OpToIndexString(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToIndexString(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToIndexString(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToIndexString decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_index;
};


struct OpUnreachable : public Instruction {
    static constexpr OpcodeID opcodeID = op_unreachable;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**unreachable"[2 - __sizeShiftAmount]);

    }

    OpUnreachable(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpUnreachable(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpUnreachable(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpUnreachable decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpCreateRest : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_rest;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, arraySize, numParametersToSkip);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, arraySize, numParametersToSkip);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, arraySize, numParametersToSkip))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, arraySize, numParametersToSkip))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, arraySize, numParametersToSkip);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& arraySize, unsigned& numParametersToSkip)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(arraySize)
            && Fits<unsigned, __size>::check(numParametersToSkip)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister arraySize, unsigned numParametersToSkip)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, arraySize, numParametersToSkip)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(arraySize));
            gen->write(Fits<unsigned, __size>::convert(numParametersToSkip));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_rest"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("arraySize", m_arraySize, false);
        dumper->dumpOperand("numParametersToSkip", m_numParametersToSkip, false);
    }

    OpCreateRest(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_arraySize(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateRest(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateRest(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateRest decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArraySize(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArraySize<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArraySize<OpcodeSize::Wide16>(value, func);
        else
            setArraySize<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArraySize(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNumParametersToSkip(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setNumParametersToSkip<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setNumParametersToSkip<OpcodeSize::Wide16>(value, func);
        else
            setNumParametersToSkip<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNumParametersToSkip(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_arraySize;
    unsigned m_numParametersToSkip;
};


struct OpGetRestLength : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_rest_length;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, numParametersToSkip);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, numParametersToSkip);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, numParametersToSkip))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, numParametersToSkip))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, numParametersToSkip);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& numParametersToSkip)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<unsigned, __size>::check(numParametersToSkip)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, numParametersToSkip)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<unsigned, __size>::convert(numParametersToSkip));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_rest_length"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("numParametersToSkip", m_numParametersToSkip, false);
    }

    OpGetRestLength(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetRestLength(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetRestLength(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetRestLength decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNumParametersToSkip(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setNumParametersToSkip<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setNumParametersToSkip<OpcodeSize::Wide16>(value, func);
        else
            setNumParametersToSkip<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNumParametersToSkip(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    unsigned m_numParametersToSkip;
};


struct OpYield : public Instruction {
    static constexpr OpcodeID opcodeID = op_yield;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, generator, yieldPoint, argument);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, generator, yieldPoint, argument);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, generator, yieldPoint, argument))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, generator, yieldPoint, argument))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, generator, yieldPoint, argument);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& generator, unsigned& yieldPoint, VirtualRegister& argument)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(generator)
            && Fits<unsigned, __size>::check(yieldPoint)
            && Fits<VirtualRegister, __size>::check(argument)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, generator, yieldPoint, argument)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(generator));
            gen->write(Fits<unsigned, __size>::convert(yieldPoint));
            gen->write(Fits<VirtualRegister, __size>::convert(argument));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**yield"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("generator", m_generator, true);
        dumper->dumpOperand("yieldPoint", m_yieldPoint, false);
        dumper->dumpOperand("argument", m_argument, false);
    }

    OpYield(const uint8_t* stream)
        : m_generator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_yieldPoint(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpYield(const uint16_t* stream)
        : m_generator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpYield(const uint32_t* stream)
        : m_generator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpYield decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setGenerator(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setGenerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setGenerator<OpcodeSize::Wide16>(value, func);
        else
            setGenerator<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGenerator(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setYieldPoint(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setYieldPoint<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setYieldPoint<OpcodeSize::Wide16>(value, func);
        else
            setYieldPoint<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setYieldPoint(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgument(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgument<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgument<OpcodeSize::Wide16>(value, func);
        else
            setArgument<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgument(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_generator;
    unsigned m_yieldPoint;
    VirtualRegister m_argument;
};


struct OpCheckTraps : public Instruction {
    static constexpr OpcodeID opcodeID = op_check_traps;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**check_traps"[2 - __sizeShiftAmount]);

    }

    OpCheckTraps(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCheckTraps(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCheckTraps(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCheckTraps decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpLogShadowChickenPrologue : public Instruction {
    static constexpr OpcodeID opcodeID = op_log_shadow_chicken_prologue;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, scope);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister scope)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, scope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, scope))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, scope))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, scope);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& scope)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(scope)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scope)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, scope)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**log_shadow_chicken_prologue"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("scope", m_scope, true);
    }

    OpLogShadowChickenPrologue(const uint8_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpLogShadowChickenPrologue(const uint16_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpLogShadowChickenPrologue(const uint32_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpLogShadowChickenPrologue decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_scope;
};


struct OpLogShadowChickenTail : public Instruction {
    static constexpr OpcodeID opcodeID = op_log_shadow_chicken_tail;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, thisValue, scope);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, thisValue, scope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, thisValue, scope))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, thisValue, scope))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, thisValue, scope);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& thisValue, VirtualRegister& scope)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(scope)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, thisValue, scope)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**log_shadow_chicken_tail"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("thisValue", m_thisValue, true);
        dumper->dumpOperand("scope", m_scope, false);
    }

    OpLogShadowChickenTail(const uint8_t* stream)
        : m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpLogShadowChickenTail(const uint16_t* stream)
        : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpLogShadowChickenTail(const uint32_t* stream)
        : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpLogShadowChickenTail decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_thisValue;
    VirtualRegister m_scope;
};


struct OpResolveScopeForHoistingFuncDeclInEval : public Instruction {
    static constexpr OpcodeID opcodeID = op_resolve_scope_for_hoisting_func_decl_in_eval;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope, property);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope, property))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope, property))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope, property);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope, unsigned& property)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && Fits<unsigned, __size>::check(property)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope, property)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            gen->write(Fits<unsigned, __size>::convert(property));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**resolve_scope_for_hoisting_func_decl_in_eval"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpResolveScopeForHoistingFuncDeclInEval(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpResolveScopeForHoistingFuncDeclInEval(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpResolveScopeForHoistingFuncDeclInEval(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpResolveScopeForHoistingFuncDeclInEval decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_property;
};


struct OpPutInternalField : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_internal_field;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned index, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, index, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned index, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, index, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned index, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, index, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, index, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, index, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& index, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(index)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned index, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, index, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(index));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_internal_field"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("index", m_index, false);
        dumper->dumpOperand("value", m_value, false);
    }

    OpPutInternalField(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutInternalField(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutInternalField(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutInternalField decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    unsigned m_index;
    VirtualRegister m_value;
};


struct OpNop : public Instruction {
    static constexpr OpcodeID opcodeID = op_nop;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**nop"[2 - __sizeShiftAmount]);

    }

    OpNop(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNop(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNop(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNop decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpSuperSamplerBegin : public Instruction {
    static constexpr OpcodeID opcodeID = op_super_sampler_begin;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**super_sampler_begin"[2 - __sizeShiftAmount]);

    }

    OpSuperSamplerBegin(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSuperSamplerBegin(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSuperSamplerBegin(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSuperSamplerBegin decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpWide16 : public Instruction {
    static constexpr OpcodeID opcodeID = op_wide16;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**wide16"[2 - __sizeShiftAmount]);

    }

    OpWide16(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpWide16(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpWide16(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpWide16 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpSuperSamplerEnd : public Instruction {
    static constexpr OpcodeID opcodeID = op_super_sampler_end;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**super_sampler_end"[2 - __sizeShiftAmount]);

    }

    OpSuperSamplerEnd(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSuperSamplerEnd(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSuperSamplerEnd(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSuperSamplerEnd decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpWide32 : public Instruction {
    static constexpr OpcodeID opcodeID = op_wide32;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**wide32"[2 - __sizeShiftAmount]);

    }

    OpWide32(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpWide32(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpWide32(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpWide32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpEnter : public Instruction {
    static constexpr OpcodeID opcodeID = op_enter;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enter"[2 - __sizeShiftAmount]);

    }

    OpEnter(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpEnter(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpEnter(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpEnter decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct OpGetScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_scope;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    OpGetScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGetScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGetScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGetScope decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct OpCreateDirectArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_direct_arguments;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_direct_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    OpCreateDirectArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateDirectArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateDirectArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateDirectArguments decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct OpCreateScopedArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_scoped_arguments;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, scope);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, scope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, scope))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, scope))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, scope);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& scope)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(scope)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, scope)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_scoped_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("scope", m_scope, false);
    }

    OpCreateScopedArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateScopedArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateScopedArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateScopedArguments decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setScope<OpcodeSize::Wide16>(value, func);
        else
            setScope<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
};


struct OpCreateClonedArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_cloned_arguments;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_cloned_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    OpCreateClonedArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateClonedArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateClonedArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateClonedArguments decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct OpCreateArgumentsButterfly : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_arguments_butterfly;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_arguments_butterfly"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    OpCreateArgumentsButterfly(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCreateArgumentsButterfly(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCreateArgumentsButterfly(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCreateArgumentsButterfly decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct OpNewPromise : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_promise;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, bool isInternalPromise)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, isInternalPromise);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, bool isInternalPromise)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, isInternalPromise);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, bool isInternalPromise)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, isInternalPromise))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, isInternalPromise))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, isInternalPromise);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, bool& isInternalPromise)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<bool, __size>::check(isInternalPromise)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, bool isInternalPromise)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, isInternalPromise)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<bool, __size>::convert(isInternalPromise));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_promise"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("isInternalPromise", m_isInternalPromise, false);
    }

    OpNewPromise(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_isInternalPromise(Fits<bool, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewPromise(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_isInternalPromise(Fits<bool, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewPromise(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_isInternalPromise(Fits<bool, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewPromise decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIsInternalPromise(bool value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setIsInternalPromise<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setIsInternalPromise<OpcodeSize::Wide16>(value, func);
        else
            setIsInternalPromise<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIsInternalPromise(bool value, Functor func)
    {
        if (!Fits<bool, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<bool, size>::convert(value);
    }

    VirtualRegister m_dst;
    bool m_isInternalPromise;
};


struct OpNewGenerator : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_generator;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_generator"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    OpNewGenerator(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewGenerator(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewGenerator(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewGenerator decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct OpArgumentCount : public Instruction {
    static constexpr OpcodeID opcodeID = op_argument_count;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**argument_count"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    OpArgumentCount(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpArgumentCount(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpArgumentCount(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpArgumentCount decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct OpCheckTdz : public Instruction {
    static constexpr OpcodeID opcodeID = op_check_tdz;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, targetVirtualRegister);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, targetVirtualRegister);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, targetVirtualRegister))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, targetVirtualRegister))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, targetVirtualRegister);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& targetVirtualRegister)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(targetVirtualRegister)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, targetVirtualRegister)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(targetVirtualRegister));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**check_tdz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("targetVirtualRegister", m_targetVirtualRegister, true);
    }

    OpCheckTdz(const uint8_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpCheckTdz(const uint16_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpCheckTdz(const uint32_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpCheckTdz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTargetVirtualRegister(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTargetVirtualRegister<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTargetVirtualRegister<OpcodeSize::Wide16>(value, func);
        else
            setTargetVirtualRegister<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetVirtualRegister(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_targetVirtualRegister;
};


struct OpNewArrayWithSpread : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array_with_spread;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, argv, argc, bitVector);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, argv, argc, bitVector);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, argv, argc, bitVector))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, argv, argc, bitVector))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, argv, argc, bitVector);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& argv, unsigned& argc, unsigned& bitVector)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(argv)
            && Fits<unsigned, __size>::check(argc)
            && Fits<unsigned, __size>::check(bitVector)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argv, unsigned argc, unsigned bitVector)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, argv, argc, bitVector)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(argv));
            gen->write(Fits<unsigned, __size>::convert(argc));
            gen->write(Fits<unsigned, __size>::convert(bitVector));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array_with_spread"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("argv", m_argv, false);
        dumper->dumpOperand("argc", m_argc, false);
        dumper->dumpOperand("bitVector", m_bitVector, false);
    }

    OpNewArrayWithSpread(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_bitVector(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewArrayWithSpread(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_bitVector(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewArrayWithSpread(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_bitVector(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewArrayWithSpread decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgv<OpcodeSize::Wide16>(value, func);
        else
            setArgv<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgv(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgc<OpcodeSize::Wide16>(value, func);
        else
            setArgc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setBitVector(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBitVector<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBitVector<OpcodeSize::Wide16>(value, func);
        else
            setBitVector<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBitVector(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_argv;
    unsigned m_argc;
    unsigned m_bitVector;
};


struct OpSpread : public Instruction {
    static constexpr OpcodeID opcodeID = op_spread;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, argument);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, argument);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, argument))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, argument))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, argument);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& argument)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(argument)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, argument)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(argument));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**spread"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("argument", m_argument, false);
    }

    OpSpread(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpSpread(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpSpread(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpSpread decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgument(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setArgument<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setArgument<OpcodeSize::Wide16>(value, func);
        else
            setArgument<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setArgument(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_argument;
};


struct OpNewRegexp : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_regexp;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, regexp);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, regexp);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, regexp))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, regexp))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, regexp);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& regexp)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(regexp)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, regexp)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(regexp));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_regexp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("regexp", m_regexp, false);
    }

    OpNewRegexp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_regexp(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNewRegexp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNewRegexp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNewRegexp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRegexp(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRegexp<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRegexp<OpcodeSize::Wide16>(value, func);
        else
            setRegexp<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRegexp(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_regexp;
};


struct OpMov : public Instruction {
    static constexpr OpcodeID opcodeID = op_mov;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, src);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, src);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, src);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(src)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, src)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(src));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mov"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("src", m_src, false);
    }

    OpMov(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpMov(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpMov(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpMov decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrc<OpcodeSize::Wide16>(value, func);
        else
            setSrc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
};


struct OpEq : public Instruction {
    static constexpr OpcodeID opcodeID = op_eq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**eq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpEq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpEq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpEq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpEq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpNeq : public Instruction {
    static constexpr OpcodeID opcodeID = op_neq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**neq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpNeq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNeq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNeq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNeq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpStricteq : public Instruction {
    static constexpr OpcodeID opcodeID = op_stricteq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**stricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpStricteq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpStricteq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpStricteq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpStricteq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpNstricteq : public Instruction {
    static constexpr OpcodeID opcodeID = op_nstricteq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**nstricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpNstricteq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNstricteq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNstricteq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNstricteq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpLess : public Instruction {
    static constexpr OpcodeID opcodeID = op_less;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**less"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpLess(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpLess(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpLess(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpLess decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpLesseq : public Instruction {
    static constexpr OpcodeID opcodeID = op_lesseq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**lesseq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpLesseq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpLesseq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpLesseq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpLesseq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpGreater : public Instruction {
    static constexpr OpcodeID opcodeID = op_greater;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**greater"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpGreater(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGreater(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGreater(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGreater decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpGreatereq : public Instruction {
    static constexpr OpcodeID opcodeID = op_greatereq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**greatereq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpGreatereq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpGreatereq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpGreatereq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpGreatereq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpBelow : public Instruction {
    static constexpr OpcodeID opcodeID = op_below;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**below"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpBelow(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpBelow(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpBelow(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpBelow decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpBeloweq : public Instruction {
    static constexpr OpcodeID opcodeID = op_beloweq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**beloweq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpBeloweq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpBeloweq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpBeloweq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpBeloweq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpMod : public Instruction {
    static constexpr OpcodeID opcodeID = op_mod;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mod"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpMod(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpMod(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpMod(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpMod decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpPow : public Instruction {
    static constexpr OpcodeID opcodeID = op_pow;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**pow"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpPow(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPow(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPow(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPow decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpUrshift : public Instruction {
    static constexpr OpcodeID opcodeID = op_urshift;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**urshift"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    OpUrshift(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpUrshift(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpUrshift(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpUrshift decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct OpEqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_eq_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**eq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpEqNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpEqNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpEqNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpEqNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpNeqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_neq_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**neq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpNeqNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNeqNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNeqNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNeqNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpToString : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_string;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_string"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpToString(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpToString(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpToString(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpToString decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpUnsigned : public Instruction {
    static constexpr OpcodeID opcodeID = op_unsigned;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**unsigned"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpUnsigned(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpUnsigned(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpUnsigned(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpUnsigned decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsEmpty : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_empty;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_empty"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsEmpty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsEmpty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsEmpty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsEmpty decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpTypeofIsUndefined : public Instruction {
    static constexpr OpcodeID opcodeID = op_typeof_is_undefined;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**typeof_is_undefined"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpTypeofIsUndefined(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTypeofIsUndefined(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTypeofIsUndefined(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTypeofIsUndefined decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpTypeofIsObject : public Instruction {
    static constexpr OpcodeID opcodeID = op_typeof_is_object;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**typeof_is_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpTypeofIsObject(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTypeofIsObject(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTypeofIsObject(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTypeofIsObject decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpTypeofIsFunction : public Instruction {
    static constexpr OpcodeID opcodeID = op_typeof_is_function;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**typeof_is_function"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpTypeofIsFunction(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTypeofIsFunction(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTypeofIsFunction(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTypeofIsFunction decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsUndefinedOrNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_undefined_or_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_undefined_or_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsUndefinedOrNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsUndefinedOrNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsUndefinedOrNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsUndefinedOrNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsBoolean : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_boolean;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_boolean"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsBoolean(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsBoolean(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsBoolean(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsBoolean decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsNumber : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_number;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_number"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsNumber(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsNumber(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsNumber(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsNumber decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsBigInt : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_big_int;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_big_int"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsBigInt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsBigInt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsBigInt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsBigInt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsObject : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_object;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsObject(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsObject(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsObject(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsObject decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsCallable : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_callable;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_callable"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsCallable(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsCallable(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsCallable(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsCallable decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIsConstructor : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_constructor;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_constructor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpIsConstructor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsConstructor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsConstructor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsConstructor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpNot : public Instruction {
    static constexpr OpcodeID opcodeID = op_not;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**not"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    OpNot(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpNot(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpNot(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpNot decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct OpIdentityWithProfile : public Instruction {
    static constexpr OpcodeID opcodeID = op_identity_with_profile;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, srcDst, topProfile, bottomProfile);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, srcDst, topProfile, bottomProfile);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, srcDst, topProfile, bottomProfile))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, srcDst, topProfile, bottomProfile))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, srcDst, topProfile, bottomProfile);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst, unsigned& topProfile, unsigned& bottomProfile)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(srcDst)
            && Fits<unsigned, __size>::check(topProfile)
            && Fits<unsigned, __size>::check(bottomProfile)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, srcDst, topProfile, bottomProfile)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(srcDst));
            gen->write(Fits<unsigned, __size>::convert(topProfile));
            gen->write(Fits<unsigned, __size>::convert(bottomProfile));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**identity_with_profile"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("srcDst", m_srcDst, true);
        dumper->dumpOperand("topProfile", m_topProfile, false);
        dumper->dumpOperand("bottomProfile", m_bottomProfile, false);
    }

    OpIdentityWithProfile(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_topProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_bottomProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIdentityWithProfile(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_topProfile(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIdentityWithProfile(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_topProfile(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIdentityWithProfile decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSrcDst<OpcodeSize::Wide16>(value, func);
        else
            setSrcDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTopProfile(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setTopProfile<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setTopProfile<OpcodeSize::Wide16>(value, func);
        else
            setTopProfile<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTopProfile(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setBottomProfile(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBottomProfile<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBottomProfile<OpcodeSize::Wide16>(value, func);
        else
            setBottomProfile<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBottomProfile(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_srcDst;
    unsigned m_topProfile;
    unsigned m_bottomProfile;
};


struct OpOverridesHasInstance : public Instruction {
    static constexpr OpcodeID opcodeID = op_overrides_has_instance;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, constructor, hasInstanceValue);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, constructor, hasInstanceValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, constructor, hasInstanceValue))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, constructor, hasInstanceValue))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, constructor, hasInstanceValue);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& constructor, VirtualRegister& hasInstanceValue)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(constructor)
            && Fits<VirtualRegister, __size>::check(hasInstanceValue)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, constructor, hasInstanceValue)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(constructor));
            gen->write(Fits<VirtualRegister, __size>::convert(hasInstanceValue));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**overrides_has_instance"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("constructor", m_constructor, false);
        dumper->dumpOperand("hasInstanceValue", m_hasInstanceValue, false);
    }

    OpOverridesHasInstance(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpOverridesHasInstance(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpOverridesHasInstance(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpOverridesHasInstance decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setConstructor(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setConstructor<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setConstructor<OpcodeSize::Wide16>(value, func);
        else
            setConstructor<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setConstructor(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setHasInstanceValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setHasInstanceValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setHasInstanceValue<OpcodeSize::Wide16>(value, func);
        else
            setHasInstanceValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setHasInstanceValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_constructor;
    VirtualRegister m_hasInstanceValue;
};


struct OpInstanceof : public Instruction {
    static constexpr OpcodeID opcodeID = op_instanceof;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, value, prototype);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, value, prototype);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, value, prototype))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, value, prototype))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, value, prototype);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value, VirtualRegister& prototype)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(prototype)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, value, prototype)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(prototype));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**instanceof"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("prototype", m_prototype, false);
    }

    OpInstanceof(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_prototype(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpInstanceof(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpInstanceof(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpInstanceof decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPrototype(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setPrototype<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setPrototype<OpcodeSize::Wide16>(value, func);
        else
            setPrototype<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPrototype(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_value;
    VirtualRegister m_prototype;
};


struct OpInstanceofCustom : public Instruction {
    static constexpr OpcodeID opcodeID = op_instanceof_custom;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, value, constructor, hasInstanceValue);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, value, constructor, hasInstanceValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, value, constructor, hasInstanceValue);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value, VirtualRegister& constructor, VirtualRegister& hasInstanceValue)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(constructor)
            && Fits<VirtualRegister, __size>::check(hasInstanceValue)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, value, constructor, hasInstanceValue)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(constructor));
            gen->write(Fits<VirtualRegister, __size>::convert(hasInstanceValue));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**instanceof_custom"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("constructor", m_constructor, false);
        dumper->dumpOperand("hasInstanceValue", m_hasInstanceValue, false);
    }

    OpInstanceofCustom(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpInstanceofCustom(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpInstanceofCustom(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpInstanceofCustom decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setConstructor(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setConstructor<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setConstructor<OpcodeSize::Wide16>(value, func);
        else
            setConstructor<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setConstructor(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setHasInstanceValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setHasInstanceValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setHasInstanceValue<OpcodeSize::Wide16>(value, func);
        else
            setHasInstanceValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setHasInstanceValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_value;
    VirtualRegister m_constructor;
    VirtualRegister m_hasInstanceValue;
};


struct OpTypeof : public Instruction {
    static constexpr OpcodeID opcodeID = op_typeof;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**typeof"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("value", m_value, false);
    }

    OpTypeof(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpTypeof(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpTypeof(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpTypeof decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_value;
};


struct OpIsCellWithType : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_cell_with_type;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand, type);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand, type);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand, type))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand, type))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand, type);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, JSType& type)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && Fits<JSType, __size>::check(type)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand, type)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            gen->write(Fits<JSType, __size>::convert(type));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_cell_with_type"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
        dumper->dumpOperand("type", m_type, false);
    }

    OpIsCellWithType(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_type(Fits<JSType, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpIsCellWithType(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_type(Fits<JSType, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpIsCellWithType(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_type(Fits<JSType, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpIsCellWithType decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setType(JSType value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setType<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setType<OpcodeSize::Wide16>(value, func);
        else
            setType<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setType(JSType value, Functor func)
    {
        if (!Fits<JSType, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<JSType, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    JSType m_type;
};


struct OpInById : public Instruction {
    static constexpr OpcodeID opcodeID = op_in_by_id;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**in_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
    }

    OpInById(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpInById(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpInById(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpInById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
};


struct OpPutByIdWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_id_with_this;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, thisValue, property, value, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value, ECMAMode ecmaMode)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, thisValue, property, value, ecmaMode);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value, ECMAMode ecmaMode)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, thisValue, property, value, ecmaMode))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, thisValue, property, value, ecmaMode))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, thisValue, property, value, ecmaMode);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& thisValue, unsigned& property, VirtualRegister& value, ECMAMode& ecmaMode)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<unsigned, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value, ECMAMode ecmaMode)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, thisValue, property, value, ecmaMode)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_id_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpPutByIdWithThis(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutByIdWithThis(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutByIdWithThis(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutByIdWithThis decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_thisValue;
    unsigned m_property;
    VirtualRegister m_value;
    ECMAMode m_ecmaMode;
};


struct OpDelById : public Instruction {
    static constexpr OpcodeID opcodeID = op_del_by_id;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, ECMAMode ecmaMode)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, ecmaMode);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, ECMAMode ecmaMode)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, ecmaMode))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, ecmaMode))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, ecmaMode);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, unsigned& property, ECMAMode& ecmaMode)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, unsigned property, ECMAMode ecmaMode)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, ecmaMode)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**del_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpDelById(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDelById(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDelById(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDelById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
    ECMAMode m_ecmaMode;
};


struct OpPutByValWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_val_with_this;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, thisValue, property, value, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, thisValue, property, value, ecmaMode);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, thisValue, property, value, ecmaMode))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, thisValue, property, value, ecmaMode))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, thisValue, property, value, ecmaMode);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& thisValue, VirtualRegister& property, VirtualRegister& value, ECMAMode& ecmaMode)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(thisValue)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value, ECMAMode ecmaMode)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, thisValue, property, value, ecmaMode)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_val_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("thisValue", m_thisValue, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpPutByValWithThis(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutByValWithThis(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutByValWithThis(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutByValWithThis decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setThisValue<OpcodeSize::Wide16>(value, func);
        else
            setThisValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_thisValue;
    VirtualRegister m_property;
    VirtualRegister m_value;
    ECMAMode m_ecmaMode;
};


struct OpDelByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_del_by_val;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, ECMAMode ecmaMode)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, base, property, ecmaMode);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, ECMAMode ecmaMode)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, base, property, ecmaMode);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, ECMAMode ecmaMode)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, ecmaMode))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, base, property, ecmaMode))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, base, property, ecmaMode);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& base, VirtualRegister& property, ECMAMode& ecmaMode)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<ECMAMode, __size>::check(ecmaMode)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base, VirtualRegister property, ECMAMode ecmaMode)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, base, property, ecmaMode)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<ECMAMode, __size>::convert(ecmaMode));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**del_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("base", m_base, false);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("ecmaMode", m_ecmaMode, false);
    }

    OpDelByVal(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpDelByVal(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpDelByVal(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_ecmaMode(Fits<ECMAMode, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpDelByVal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setEcmaMode<OpcodeSize::Wide16>(value, func);
        else
            setEcmaMode<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setEcmaMode(ECMAMode value, Functor func)
    {
        if (!Fits<ECMAMode, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<ECMAMode, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    ECMAMode m_ecmaMode;
};


struct OpPutGetterById : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_getter_by_id;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, attributes, accessor);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, attributes, accessor);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, unsigned& attributes, VirtualRegister& accessor)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(attributes)
            && Fits<VirtualRegister, __size>::check(accessor)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, attributes, accessor)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(attributes));
            gen->write(Fits<VirtualRegister, __size>::convert(accessor));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_getter_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("attributes", m_attributes, false);
        dumper->dumpOperand("accessor", m_accessor, false);
    }

    OpPutGetterById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutGetterById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutGetterById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutGetterById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide16>(value, func);
        else
            setAccessor<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    unsigned m_property;
    unsigned m_attributes;
    VirtualRegister m_accessor;
};


struct OpPutSetterById : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_setter_by_id;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, attributes, accessor);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, attributes, accessor);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, unsigned& attributes, VirtualRegister& accessor)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(attributes)
            && Fits<VirtualRegister, __size>::check(accessor)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, attributes, accessor)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(attributes));
            gen->write(Fits<VirtualRegister, __size>::convert(accessor));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_setter_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("attributes", m_attributes, false);
        dumper->dumpOperand("accessor", m_accessor, false);
    }

    OpPutSetterById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutSetterById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutSetterById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutSetterById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide16>(value, func);
        else
            setAccessor<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    unsigned m_property;
    unsigned m_attributes;
    VirtualRegister m_accessor;
};


struct OpPutGetterSetterById : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_getter_setter_by_id;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, attributes, getter, setter);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, attributes, getter, setter);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, getter, setter))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, getter, setter))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, attributes, getter, setter);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, unsigned& property, unsigned& attributes, VirtualRegister& getter, VirtualRegister& setter)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<unsigned, __size>::check(property)
            && Fits<unsigned, __size>::check(attributes)
            && Fits<VirtualRegister, __size>::check(getter)
            && Fits<VirtualRegister, __size>::check(setter)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, attributes, getter, setter)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<unsigned, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(attributes));
            gen->write(Fits<VirtualRegister, __size>::convert(getter));
            gen->write(Fits<VirtualRegister, __size>::convert(setter));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_getter_setter_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("attributes", m_attributes, false);
        dumper->dumpOperand("getter", m_getter, false);
        dumper->dumpOperand("setter", m_setter, false);
    }

    OpPutGetterSetterById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutGetterSetterById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutGetterSetterById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutGetterSetterById decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setGetter(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setGetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setGetter<OpcodeSize::Wide16>(value, func);
        else
            setGetter<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGetter(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSetter(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setSetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setSetter<OpcodeSize::Wide16>(value, func);
        else
            setSetter<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSetter(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    unsigned m_property;
    unsigned m_attributes;
    VirtualRegister m_getter;
    VirtualRegister m_setter;
};


struct OpPutGetterByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_getter_by_val;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, base, property, attributes, accessor);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, base, property, attributes, accessor);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, unsigned& attributes, VirtualRegister& accessor)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<OpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(base)
            && Fits<VirtualRegister, __size>::check(property)
            && Fits<unsigned, __size>::check(attributes)
            && Fits<VirtualRegister, __size>::check(accessor)
            && (__size == OpcodeSize::Wide16 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<OpcodeID, OpcodeSize::Narrow>::check(op_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, base, property, attributes, accessor)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(op_wide32));
            gen->write(Fits<OpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(base));
            gen->write(Fits<VirtualRegister, __size>::convert(property));
            gen->write(Fits<unsigned, __size>::convert(attributes));
            gen->write(Fits<VirtualRegister, __size>::convert(accessor));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_getter_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("base", m_base, true);
        dumper->dumpOperand("property", m_property, false);
        dumper->dumpOperand("attributes", m_attributes, false);
        dumper->dumpOperand("accessor", m_accessor, false);
    }

    OpPutGetterByVal(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    OpPutGetterByVal(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    OpPutGetterByVal(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static OpPutGetterByVal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == op_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == op_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setBase<OpcodeSize::Wide16>(value, func);
        else
            setBase<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setProperty<OpcodeSize::Wide16>(value, func);
        else
            setProperty<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAttributes<OpcodeSize::Wide16>(value, func);
        else
            setAttributes<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16<JSOpcodeTraits>())
            setAccessor<OpcodeSize::Wide16>(value, func);
        else
            setAccessor<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_attributes;
    VirtualRegister m_accessor;
};



#if ENABLE(WEBASSEMBLY)
struct WasmAtomicFence : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_atomic_fence;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**atomic_fence"[2 - __sizeShiftAmount]);

    }

    WasmAtomicFence(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmAtomicFence(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmAtomicFence(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmAtomicFence decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmI32Sub : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_sub;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Sub(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Sub(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Sub(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Sub decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Mul : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_mul;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_mul"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Mul(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Mul(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Mul(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Mul decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32DivS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_div_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_div_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32DivS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32DivS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32DivS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32DivS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32DivU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_div_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_div_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32DivU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32DivU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32DivU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32DivU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32RemS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_rem_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_rem_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32RemS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32RemS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32RemS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32RemS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32RemU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_rem_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_rem_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32RemU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32RemU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32RemU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32RemU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32And : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_and;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_and"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32And(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32And(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32And(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32And decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Or : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_or;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_or"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Or(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Or(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Or(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Or decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Xor : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_xor;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_xor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Xor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Xor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Xor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Xor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Shl : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_shl;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_shl"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Shl(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Shl(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Shl(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Shl decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32ShrU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_shr_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_shr_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32ShrU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32ShrU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32ShrU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32ShrU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32ShrS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_shr_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_shr_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32ShrS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32ShrS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32ShrS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32ShrS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Rotr : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_rotr;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_rotr"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Rotr(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Rotr(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Rotr(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Rotr decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Rotl : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_rotl;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_rotl"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Rotl(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Rotl(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Rotl(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Rotl decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Eq : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_eq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_eq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Eq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Eq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Eq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Eq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Ne : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_ne;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_ne"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Ne(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Ne(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Ne(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Ne decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32LtS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_lt_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_lt_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32LtS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32LtS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32LtS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32LtS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32LeS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_le_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_le_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32LeS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32LeS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32LeS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32LeS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32LtU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_lt_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_lt_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32LtU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32LtU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32LtU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32LtU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32LeU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_le_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_le_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32LeU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32LeU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32LeU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32LeU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32GtS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_gt_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_gt_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32GtS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32GtS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32GtS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32GtS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32GeS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_ge_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_ge_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32GeS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32GeS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32GeS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32GeS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32GtU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_gt_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_gt_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32GtU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32GtU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32GtU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32GtU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32GeU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_ge_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_ge_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32GeU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32GeU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32GeU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32GeU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32Clz : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_clz;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_clz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32Clz(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Clz(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Clz(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Clz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32Ctz : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_ctz;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_ctz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32Ctz(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Ctz(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Ctz(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Ctz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32Popcnt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_popcnt;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_popcnt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32Popcnt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Popcnt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Popcnt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Popcnt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32Eqz : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_eqz;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_eqz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32Eqz(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Eqz(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Eqz(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Eqz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Add : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_add;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Add(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Add(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Add(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Add decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Sub : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_sub;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Sub(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Sub(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Sub(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Sub decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Mul : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_mul;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_mul"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Mul(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Mul(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Mul(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Mul decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64DivS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_div_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_div_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64DivS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64DivS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64DivS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64DivS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64DivU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_div_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_div_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64DivU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64DivU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64DivU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64DivU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64RemS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_rem_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_rem_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64RemS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64RemS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64RemS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64RemS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64RemU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_rem_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_rem_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64RemU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64RemU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64RemU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64RemU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64And : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_and;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_and"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64And(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64And(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64And(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64And decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Or : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_or;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_or"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Or(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Or(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Or(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Or decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Xor : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_xor;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_xor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Xor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Xor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Xor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Xor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Shl : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_shl;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_shl"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Shl(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Shl(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Shl(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Shl decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64ShrU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_shr_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_shr_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64ShrU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64ShrU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64ShrU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64ShrU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64ShrS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_shr_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_shr_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64ShrS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64ShrS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64ShrS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64ShrS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Rotr : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_rotr;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_rotr"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Rotr(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Rotr(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Rotr(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Rotr decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Rotl : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_rotl;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_rotl"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Rotl(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Rotl(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Rotl(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Rotl decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Eq : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_eq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_eq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Eq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Eq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Eq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Eq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Ne : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_ne;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_ne"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64Ne(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Ne(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Ne(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Ne decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64LtS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_lt_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_lt_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64LtS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64LtS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64LtS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64LtS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64LeS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_le_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_le_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64LeS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64LeS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64LeS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64LeS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64LtU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_lt_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_lt_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64LtU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64LtU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64LtU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64LtU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64LeU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_le_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_le_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64LeU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64LeU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64LeU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64LeU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64GtS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_gt_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_gt_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64GtS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64GtS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64GtS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64GtS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64GeS : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_ge_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_ge_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64GeS(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64GeS(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64GeS(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64GeS decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64GtU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_gt_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_gt_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64GtU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64GtU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64GtU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64GtU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64GeU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_ge_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_ge_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI64GeU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64GeU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64GeU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64GeU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI64Clz : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_clz;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_clz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Clz(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Clz(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Clz(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Clz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Ctz : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_ctz;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_ctz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Ctz(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Ctz(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Ctz(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Ctz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Popcnt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_popcnt;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_popcnt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Popcnt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Popcnt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Popcnt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Popcnt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Eqz : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_eqz;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_eqz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Eqz(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Eqz(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Eqz(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Eqz decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Add : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_add;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Add(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Add(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Add(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Add decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Sub : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_sub;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Sub(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Sub(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Sub(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Sub decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Mul : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_mul;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_mul"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Mul(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Mul(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Mul(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Mul decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Div : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_div;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_div"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Div(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Div(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Div(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Div decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Min : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_min;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_min"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Min(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Min(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Min(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Min decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Max : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_max;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_max"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Max(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Max(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Max(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Max decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Abs : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_abs;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_abs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Abs(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Abs(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Abs(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Abs decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Neg : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_neg;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_neg"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Neg(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Neg(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Neg(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Neg decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Copysign : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_copysign;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_copysign"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Copysign(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Copysign(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Copysign(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Copysign decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Ceil : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_ceil;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_ceil"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Ceil(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Ceil(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Ceil(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Ceil decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Floor : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_floor;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_floor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Floor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Floor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Floor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Floor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Trunc : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_trunc;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_trunc"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Trunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Trunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Trunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Trunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Nearest : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_nearest;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_nearest"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Nearest(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Nearest(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Nearest(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Nearest decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Sqrt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_sqrt;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_sqrt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32Sqrt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Sqrt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Sqrt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Sqrt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32Eq : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_eq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_eq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Eq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Eq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Eq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Eq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Ne : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_ne;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_ne"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Ne(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Ne(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Ne(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Ne decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Lt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_lt;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_lt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Lt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Lt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Lt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Lt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Le : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_le;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_le"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Le(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Le(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Le(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Le decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Gt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_gt;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_gt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Gt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Gt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Gt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Gt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF32Ge : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_ge;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_ge"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF32Ge(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32Ge(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32Ge(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32Ge decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Add : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_add;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Add(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Add(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Add(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Add decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Sub : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_sub;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Sub(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Sub(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Sub(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Sub decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Mul : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_mul;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_mul"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Mul(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Mul(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Mul(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Mul decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Div : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_div;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_div"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Div(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Div(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Div(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Div decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Min : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_min;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_min"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Min(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Min(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Min(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Min decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Max : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_max;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_max"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Max(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Max(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Max(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Max decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Abs : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_abs;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_abs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Abs(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Abs(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Abs(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Abs decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Neg : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_neg;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_neg"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Neg(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Neg(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Neg(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Neg decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Copysign : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_copysign;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_copysign"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Copysign(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Copysign(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Copysign(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Copysign decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Ceil : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_ceil;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_ceil"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Ceil(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Ceil(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Ceil(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Ceil decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Floor : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_floor;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_floor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Floor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Floor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Floor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Floor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Trunc : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_trunc;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_trunc"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Trunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Trunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Trunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Trunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Nearest : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_nearest;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_nearest"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Nearest(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Nearest(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Nearest(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Nearest decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Sqrt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_sqrt;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_sqrt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64Sqrt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Sqrt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Sqrt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Sqrt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64Eq : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_eq;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_eq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Eq(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Eq(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Eq(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Eq decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Ne : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_ne;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_ne"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Ne(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Ne(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Ne(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Ne decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Lt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_lt;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_lt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Lt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Lt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Lt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Lt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Le : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_le;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_le"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Le(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Le(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Le(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Le decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Gt : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_gt;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_gt"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Gt(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Gt(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Gt(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Gt decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmF64Ge : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_ge;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_ge"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmF64Ge(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64Ge(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64Ge(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64Ge decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


struct WasmI32TruncSF32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_trunc_s_f32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_trunc_s_f32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32TruncSF32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32TruncSF32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32TruncSF32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32TruncSF32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32TruncSF64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_trunc_s_f64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_trunc_s_f64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32TruncSF64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32TruncSF64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32TruncSF64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32TruncSF64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32TruncUF32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_trunc_u_f32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_trunc_u_f32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32TruncUF32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32TruncUF32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32TruncUF32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32TruncUF32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32TruncUF64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_trunc_u_f64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_trunc_u_f64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32TruncUF64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32TruncUF64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32TruncUF64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32TruncUF64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32WrapI64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_wrap_i64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_wrap_i64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32WrapI64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32WrapI64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32WrapI64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32WrapI64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64TruncSF32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_trunc_s_f32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_trunc_s_f32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64TruncSF32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64TruncSF32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64TruncSF32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64TruncSF32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64TruncSF64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_trunc_s_f64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_trunc_s_f64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64TruncSF64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64TruncSF64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64TruncSF64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64TruncSF64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64TruncUF32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_trunc_u_f32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_trunc_u_f32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64TruncUF32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64TruncUF32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64TruncUF32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64TruncUF32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64TruncUF64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_trunc_u_f64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_trunc_u_f64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64TruncUF64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64TruncUF64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64TruncUF64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64TruncUF64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64ExtendSI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_extend_s_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_extend_s_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64ExtendSI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64ExtendSI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64ExtendSI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64ExtendSI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64ExtendUI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_extend_u_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_extend_u_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64ExtendUI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64ExtendUI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64ExtendUI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64ExtendUI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32ConvertSI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_convert_s_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_convert_s_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32ConvertSI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32ConvertSI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32ConvertSI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32ConvertSI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32ConvertUI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_convert_u_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_convert_u_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32ConvertUI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32ConvertUI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32ConvertUI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32ConvertUI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32ConvertSI64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_convert_s_i64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_convert_s_i64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32ConvertSI64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32ConvertSI64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32ConvertSI64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32ConvertSI64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32ConvertUI64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_convert_u_i64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_convert_u_i64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32ConvertUI64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32ConvertUI64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32ConvertUI64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32ConvertUI64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32DemoteF64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_demote_f64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_demote_f64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32DemoteF64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32DemoteF64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32DemoteF64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32DemoteF64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF32ReinterpretI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f32_reinterpret_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f32_reinterpret_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF32ReinterpretI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF32ReinterpretI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF32ReinterpretI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF32ReinterpretI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64ConvertSI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_convert_s_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_convert_s_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64ConvertSI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64ConvertSI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64ConvertSI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64ConvertSI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64ConvertUI32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_convert_u_i32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_convert_u_i32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64ConvertUI32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64ConvertUI32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64ConvertUI32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64ConvertUI32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64ConvertSI64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_convert_s_i64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_convert_s_i64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64ConvertSI64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64ConvertSI64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64ConvertSI64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64ConvertSI64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64ConvertUI64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_convert_u_i64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_convert_u_i64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64ConvertUI64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64ConvertUI64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64ConvertUI64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64ConvertUI64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64PromoteF32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_promote_f32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_promote_f32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64PromoteF32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64PromoteF32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64PromoteF32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64PromoteF32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmF64ReinterpretI64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_f64_reinterpret_i64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**f64_reinterpret_i64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmF64ReinterpretI64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmF64ReinterpretI64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmF64ReinterpretI64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmF64ReinterpretI64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32ReinterpretF32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_reinterpret_f32;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_reinterpret_f32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32ReinterpretF32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32ReinterpretF32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32ReinterpretF32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32ReinterpretF32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64ReinterpretF64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_reinterpret_f64;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_reinterpret_f64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64ReinterpretF64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64ReinterpretF64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64ReinterpretF64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64ReinterpretF64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32Extend8S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_extend8_s;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_extend8_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32Extend8S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Extend8S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Extend8S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Extend8S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI32Extend16S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_extend16_s;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_extend16_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI32Extend16S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Extend16S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Extend16S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Extend16S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Extend8S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_extend8_s;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_extend8_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Extend8S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Extend8S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Extend8S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Extend8S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Extend16S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_extend16_s;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_extend16_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Extend16S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Extend16S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Extend16S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Extend16S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmI64Extend32S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_extend32_s;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, operand);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, operand);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(operand)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, operand)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_extend32_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("operand", m_operand, false);
    }

    WasmI64Extend32S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Extend32S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Extend32S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Extend32S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOperand<OpcodeSize::Wide16>(value, func);
        else
            setOperand<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};


struct WasmThrowFromSlowPathTrampoline : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_throw_from_slow_path_trampoline;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**throw_from_slow_path_trampoline"[2 - __sizeShiftAmount]);

    }

    WasmThrowFromSlowPathTrampoline(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmThrowFromSlowPathTrampoline(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmThrowFromSlowPathTrampoline(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmThrowFromSlowPathTrampoline decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmThrowFromFaultHandlerTrampoline : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_throw_from_fault_handler_trampoline;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**throw_from_fault_handler_trampoline"[2 - __sizeShiftAmount]);

    }

    WasmThrowFromFaultHandlerTrampoline(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmThrowFromFaultHandlerTrampoline(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmThrowFromFaultHandlerTrampoline(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmThrowFromFaultHandlerTrampoline decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmCallReturnLocation : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_return_location;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_return_location"[2 - __sizeShiftAmount]);

    }

    WasmCallReturnLocation(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallReturnLocation(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallReturnLocation(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallReturnLocation decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmCallNoTlsReturnLocation : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_no_tls_return_location;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_no_tls_return_location"[2 - __sizeShiftAmount]);

    }

    WasmCallNoTlsReturnLocation(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallNoTlsReturnLocation(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallNoTlsReturnLocation(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallNoTlsReturnLocation decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmCallIndirectReturnLocation : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_indirect_return_location;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_indirect_return_location"[2 - __sizeShiftAmount]);

    }

    WasmCallIndirectReturnLocation(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallIndirectReturnLocation(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallIndirectReturnLocation(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallIndirectReturnLocation decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmCallIndirectNoTlsReturnLocation : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_indirect_no_tls_return_location;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_indirect_no_tls_return_location"[2 - __sizeShiftAmount]);

    }

    WasmCallIndirectNoTlsReturnLocation(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallIndirectNoTlsReturnLocation(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallIndirectNoTlsReturnLocation(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallIndirectNoTlsReturnLocation decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmWide16 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_wide16;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**wide16"[2 - __sizeShiftAmount]);

    }

    WasmWide16(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmWide16(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmWide16(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmWide16 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmWide32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_wide32;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**wide32"[2 - __sizeShiftAmount]);

    }

    WasmWide32(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmWide32(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmWide32(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmWide32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmEnter : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_enter;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enter"[2 - __sizeShiftAmount]);

    }

    WasmEnter(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmEnter(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmEnter(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmEnter decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmNop : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_nop;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**nop"[2 - __sizeShiftAmount]);

    }

    WasmNop(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmNop(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmNop(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmNop decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmLoopHint : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_loop_hint;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**loop_hint"[2 - __sizeShiftAmount]);

    }

    WasmLoopHint(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmLoopHint(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmLoopHint(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmLoopHint decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmMov : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_mov;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, src);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, src);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, src))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, src);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& src)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(src)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, src)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(src));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mov"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("src", m_src, false);
    }

    WasmMov(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMov(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMov(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMov decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSrc<OpcodeSize::Wide16>(value, func);
        else
            setSrc<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
};


struct WasmJtrue : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_jtrue;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, condition, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, condition, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, condition, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& condition, WasmBoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(condition)
            && Fits<WasmBoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, condition, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(condition));
            gen->write(Fits<WasmBoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jtrue"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("condition", m_condition, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    WasmJtrue(const uint8_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmJtrue(const uint16_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmJtrue(const uint32_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmJtrue decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setCondition<OpcodeSize::Wide16>(value, func);
        else
            setCondition<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(WasmBoundLabel value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(WasmBoundLabel value, Functor func)
    {
        if (!Fits<WasmBoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<WasmBoundLabel, size>::convert(value);
    }

    VirtualRegister m_condition;
    WasmBoundLabel m_targetLabel;
};


struct WasmJfalse : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_jfalse;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, condition, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, condition, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, condition, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& condition, WasmBoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(condition)
            && Fits<WasmBoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister condition, WasmBoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, condition, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(condition));
            gen->write(Fits<WasmBoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jfalse"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("condition", m_condition, true);
        dumper->dumpOperand("targetLabel", m_targetLabel, false);
    }

    WasmJfalse(const uint8_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmJfalse(const uint16_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmJfalse(const uint32_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmJfalse decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setCondition<OpcodeSize::Wide16>(value, func);
        else
            setCondition<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(WasmBoundLabel value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(WasmBoundLabel value, Functor func)
    {
        if (!Fits<WasmBoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<WasmBoundLabel, size>::convert(value);
    }

    VirtualRegister m_condition;
    WasmBoundLabel m_targetLabel;
};


struct WasmJmp : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_jmp;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, WasmBoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, targetLabel);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, WasmBoundLabel targetLabel)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, WasmBoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, targetLabel))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, targetLabel);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, WasmBoundLabel& targetLabel)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<WasmBoundLabel, __size>::check(targetLabel)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, WasmBoundLabel targetLabel)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, targetLabel)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<WasmBoundLabel, __size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jmp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("targetLabel", m_targetLabel, true);
    }

    WasmJmp(const uint8_t* stream)
        : m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmJmp(const uint16_t* stream)
        : m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmJmp(const uint32_t* stream)
        : m_targetLabel(Fits<WasmBoundLabel, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmJmp decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setTargetLabel(WasmBoundLabel value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTargetLabel<OpcodeSize::Wide16>(value, func);
        else
            setTargetLabel<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetLabel(WasmBoundLabel value, Functor func)
    {
        if (!Fits<WasmBoundLabel, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<WasmBoundLabel, size>::convert(value);
    }

    WasmBoundLabel m_targetLabel;
};


struct WasmRet : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_ret;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**ret"[2 - __sizeShiftAmount]);

    }

    WasmRet(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmRet(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmRet(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmRet decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmSwitch : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_switch;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister scrutinee, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, scrutinee, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister scrutinee, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, scrutinee, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister scrutinee, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, scrutinee, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, scrutinee, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, scrutinee, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& scrutinee, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(scrutinee)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister scrutinee, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, scrutinee, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(scrutinee));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("scrutinee", m_scrutinee, true);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmSwitch(const uint8_t* stream)
        : m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmSwitch(const uint16_t* stream)
        : m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmSwitch(const uint32_t* stream)
        : m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmSwitch decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setScrutinee<OpcodeSize::Wide16>(value, func);
        else
            setScrutinee<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_scrutinee;
    unsigned m_tableIndex;
};


struct WasmUnreachable : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_unreachable;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**unreachable"[2 - __sizeShiftAmount]);

    }

    WasmUnreachable(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmUnreachable(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmUnreachable(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmUnreachable decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmRetVoid : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_ret_void;
    static constexpr size_t length = 1;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));

            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**ret_void"[2 - __sizeShiftAmount]);

    }

    WasmRetVoid(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmRetVoid(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmRetVoid(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmRetVoid decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }



};


struct WasmDropKeep : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_drop_keep;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned startOffset, unsigned dropCount, unsigned keepCount)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, startOffset, dropCount, keepCount);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned startOffset, unsigned dropCount, unsigned keepCount)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, startOffset, dropCount, keepCount);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned startOffset, unsigned dropCount, unsigned keepCount)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, startOffset, dropCount, keepCount))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, startOffset, dropCount, keepCount))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, startOffset, dropCount, keepCount);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& startOffset, unsigned& dropCount, unsigned& keepCount)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(startOffset)
            && Fits<unsigned, __size>::check(dropCount)
            && Fits<unsigned, __size>::check(keepCount)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned startOffset, unsigned dropCount, unsigned keepCount)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, startOffset, dropCount, keepCount)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(startOffset));
            gen->write(Fits<unsigned, __size>::convert(dropCount));
            gen->write(Fits<unsigned, __size>::convert(keepCount));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**drop_keep"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("startOffset", m_startOffset, true);
        dumper->dumpOperand("dropCount", m_dropCount, false);
        dumper->dumpOperand("keepCount", m_keepCount, false);
    }

    WasmDropKeep(const uint8_t* stream)
        : m_startOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_dropCount(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_keepCount(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmDropKeep(const uint16_t* stream)
        : m_startOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_dropCount(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_keepCount(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmDropKeep(const uint32_t* stream)
        : m_startOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_dropCount(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_keepCount(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmDropKeep decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setStartOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setStartOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setStartOffset<OpcodeSize::Wide16>(value, func);
        else
            setStartOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStartOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDropCount(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDropCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDropCount<OpcodeSize::Wide16>(value, func);
        else
            setDropCount<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDropCount(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setKeepCount(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setKeepCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setKeepCount<OpcodeSize::Wide16>(value, func);
        else
            setKeepCount<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setKeepCount(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    unsigned m_startOffset;
    unsigned m_dropCount;
    unsigned m_keepCount;
};


struct WasmRefIsNull : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_ref_is_null;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister ref)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, ref);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister ref)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, ref);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister ref)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, ref))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, ref))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, ref);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& ref)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(ref)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister ref)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, ref)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(ref));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**ref_is_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("ref", m_ref, false);
    }

    WasmRefIsNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_ref(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmRefIsNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_ref(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmRefIsNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_ref(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmRefIsNull decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRef(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRef<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRef<OpcodeSize::Wide16>(value, func);
        else
            setRef<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRef(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_ref;
};


struct WasmRefFunc : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_ref_func;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned functionIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, functionIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned functionIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, functionIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned functionIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, functionIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, functionIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, functionIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& functionIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<unsigned, __size>::check(functionIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned functionIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, functionIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<unsigned, __size>::convert(functionIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**ref_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("functionIndex", m_functionIndex, false);
    }

    WasmRefFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_functionIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmRefFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_functionIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmRefFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_functionIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmRefFunc decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide16>(value, func);
        else
            setFunctionIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    unsigned m_functionIndex;
};


struct WasmGetGlobal : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_get_global;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, globalIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, globalIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, globalIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, globalIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, globalIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& globalIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<unsigned, __size>::check(globalIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, globalIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<unsigned, __size>::convert(globalIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_global"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("globalIndex", m_globalIndex, false);
    }

    WasmGetGlobal(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_globalIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmGetGlobal(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_globalIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmGetGlobal(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_globalIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmGetGlobal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide16>(value, func);
        else
            setGlobalIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    unsigned m_globalIndex;
};


struct WasmSetGlobal : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_set_global;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, globalIndex, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, globalIndex, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, globalIndex, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& globalIndex, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(globalIndex)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, globalIndex, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(globalIndex));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**set_global"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("globalIndex", m_globalIndex, true);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmSetGlobal(const uint8_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmSetGlobal(const uint16_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmSetGlobal(const uint32_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmSetGlobal decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide16>(value, func);
        else
            setGlobalIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_globalIndex;
    VirtualRegister m_value;
};


struct WasmSetGlobalRef : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_set_global_ref;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, globalIndex, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, globalIndex, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, globalIndex, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& globalIndex, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(globalIndex)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, globalIndex, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(globalIndex));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**set_global_ref"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("globalIndex", m_globalIndex, true);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmSetGlobalRef(const uint8_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmSetGlobalRef(const uint16_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmSetGlobalRef(const uint32_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmSetGlobalRef decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide16>(value, func);
        else
            setGlobalIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_globalIndex;
    VirtualRegister m_value;
};


struct WasmGetGlobalPortableBinding : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_get_global_portable_binding;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, globalIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, globalIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, globalIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, globalIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, globalIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& globalIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<unsigned, __size>::check(globalIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned globalIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, globalIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<unsigned, __size>::convert(globalIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_global_portable_binding"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("globalIndex", m_globalIndex, false);
    }

    WasmGetGlobalPortableBinding(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_globalIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmGetGlobalPortableBinding(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_globalIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmGetGlobalPortableBinding(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_globalIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmGetGlobalPortableBinding decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide16>(value, func);
        else
            setGlobalIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    unsigned m_globalIndex;
};


struct WasmSetGlobalPortableBinding : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_set_global_portable_binding;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, globalIndex, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, globalIndex, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, globalIndex, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& globalIndex, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(globalIndex)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, globalIndex, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(globalIndex));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**set_global_portable_binding"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("globalIndex", m_globalIndex, true);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmSetGlobalPortableBinding(const uint8_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmSetGlobalPortableBinding(const uint16_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmSetGlobalPortableBinding(const uint32_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmSetGlobalPortableBinding decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide16>(value, func);
        else
            setGlobalIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_globalIndex;
    VirtualRegister m_value;
};


struct WasmSetGlobalRefPortableBinding : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_set_global_ref_portable_binding;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, globalIndex, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, globalIndex, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, globalIndex, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, globalIndex, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& globalIndex, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(globalIndex)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned globalIndex, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, globalIndex, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(globalIndex));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**set_global_ref_portable_binding"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("globalIndex", m_globalIndex, true);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmSetGlobalRefPortableBinding(const uint8_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmSetGlobalRefPortableBinding(const uint16_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmSetGlobalRefPortableBinding(const uint32_t* stream)
        : m_globalIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmSetGlobalRefPortableBinding decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setGlobalIndex<OpcodeSize::Wide16>(value, func);
        else
            setGlobalIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setGlobalIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    unsigned m_globalIndex;
    VirtualRegister m_value;
};


struct WasmTableGet : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_get;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, index, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, index, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, index, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, index, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, index, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& index, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(index)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, index, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(index));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_get"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("index", m_index, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmTableGet(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableGet(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableGet(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableGet decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_index;
    unsigned m_tableIndex;
};


struct WasmTableSet : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_set;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister index, VirtualRegister value, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, index, value, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister index, VirtualRegister value, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, index, value, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister index, VirtualRegister value, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, index, value, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, index, value, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, index, value, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& index, VirtualRegister& value, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(index)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister index, VirtualRegister value, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, index, value, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(index));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_set"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("index", m_index, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmTableSet(const uint8_t* stream)
        : m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableSet(const uint16_t* stream)
        : m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableSet(const uint32_t* stream)
        : m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableSet decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setIndex<OpcodeSize::Wide16>(value, func);
        else
            setIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_index;
    VirtualRegister m_value;
    unsigned m_tableIndex;
};


struct WasmTableInit : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_init;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned elementIndex, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dstOffset, srcOffset, length, elementIndex, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned elementIndex, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dstOffset, srcOffset, length, elementIndex, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned elementIndex, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dstOffset, srcOffset, length, elementIndex, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dstOffset, srcOffset, length, elementIndex, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dstOffset, srcOffset, length, elementIndex, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dstOffset, VirtualRegister& srcOffset, VirtualRegister& length, unsigned& elementIndex, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dstOffset)
            && Fits<VirtualRegister, __size>::check(srcOffset)
            && Fits<VirtualRegister, __size>::check(length)
            && Fits<unsigned, __size>::check(elementIndex)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned elementIndex, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dstOffset, srcOffset, length, elementIndex, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dstOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(srcOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(length));
            gen->write(Fits<unsigned, __size>::convert(elementIndex));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_init"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dstOffset", m_dstOffset, true);
        dumper->dumpOperand("srcOffset", m_srcOffset, false);
        dumper->dumpOperand("length", m_length, false);
        dumper->dumpOperand("elementIndex", m_elementIndex, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmTableInit(const uint8_t* stream)
        : m_dstOffset(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_srcOffset(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_elementIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableInit(const uint16_t* stream)
        : m_dstOffset(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_srcOffset(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_elementIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableInit(const uint32_t* stream)
        : m_dstOffset(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_srcOffset(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_elementIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableInit decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDstOffset(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDstOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDstOffset<OpcodeSize::Wide16>(value, func);
        else
            setDstOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDstOffset(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrcOffset(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSrcOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSrcOffset<OpcodeSize::Wide16>(value, func);
        else
            setSrcOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcOffset(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLength<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLength<OpcodeSize::Wide16>(value, func);
        else
            setLength<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setElementIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setElementIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setElementIndex<OpcodeSize::Wide16>(value, func);
        else
            setElementIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setElementIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dstOffset;
    VirtualRegister m_srcOffset;
    VirtualRegister m_length;
    unsigned m_elementIndex;
    unsigned m_tableIndex;
};


struct WasmElemDrop : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_elem_drop;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned elementIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, elementIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned elementIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, elementIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned elementIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, elementIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, elementIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, elementIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& elementIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(elementIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned elementIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, elementIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(elementIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**elem_drop"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("elementIndex", m_elementIndex, true);
    }

    WasmElemDrop(const uint8_t* stream)
        : m_elementIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmElemDrop(const uint16_t* stream)
        : m_elementIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmElemDrop(const uint32_t* stream)
        : m_elementIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmElemDrop decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setElementIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setElementIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setElementIndex<OpcodeSize::Wide16>(value, func);
        else
            setElementIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setElementIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    unsigned m_elementIndex;
};


struct WasmTableSize : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_size;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_size"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmTableSize(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableSize(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableSize(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableSize decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    unsigned m_tableIndex;
};


struct WasmTableGrow : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_grow;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, fill, size, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, fill, size, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, fill, size, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, fill, size, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, fill, size, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& fill, VirtualRegister& size, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(fill)
            && Fits<VirtualRegister, __size>::check(size)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, fill, size, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(fill));
            gen->write(Fits<VirtualRegister, __size>::convert(size));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_grow"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("fill", m_fill, false);
        dumper->dumpOperand("size", m_size, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmTableGrow(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_fill(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_size(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableGrow(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_fill(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_size(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableGrow(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_fill(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_size(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableGrow decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFill(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFill<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFill<OpcodeSize::Wide16>(value, func);
        else
            setFill<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFill(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSize(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSize<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSize<OpcodeSize::Wide16>(value, func);
        else
            setSize<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSize(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_fill;
    VirtualRegister m_size;
    unsigned m_tableIndex;
};


struct WasmTableFill : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_fill;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister offset, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, offset, fill, size, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister offset, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, offset, fill, size, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister offset, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, offset, fill, size, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, offset, fill, size, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, offset, fill, size, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& offset, VirtualRegister& fill, VirtualRegister& size, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(fill)
            && Fits<VirtualRegister, __size>::check(size)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister offset, VirtualRegister fill, VirtualRegister size, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, offset, fill, size, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(fill));
            gen->write(Fits<VirtualRegister, __size>::convert(size));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_fill"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("offset", m_offset, true);
        dumper->dumpOperand("fill", m_fill, false);
        dumper->dumpOperand("size", m_size, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmTableFill(const uint8_t* stream)
        : m_offset(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_fill(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_size(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableFill(const uint16_t* stream)
        : m_offset(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_fill(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_size(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableFill(const uint32_t* stream)
        : m_offset(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_fill(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_size(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableFill decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setOffset(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFill(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFill<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFill<OpcodeSize::Wide16>(value, func);
        else
            setFill<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFill(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSize(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSize<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSize<OpcodeSize::Wide16>(value, func);
        else
            setSize<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSize(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_offset;
    VirtualRegister m_fill;
    VirtualRegister m_size;
    unsigned m_tableIndex;
};


struct WasmTableCopy : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_table_copy;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned dstTableIndex, unsigned srcTableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dstOffset, srcOffset, length, dstTableIndex, srcTableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned dstTableIndex, unsigned srcTableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dstOffset, srcOffset, length, dstTableIndex, srcTableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned dstTableIndex, unsigned srcTableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dstOffset, srcOffset, length, dstTableIndex, srcTableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dstOffset, srcOffset, length, dstTableIndex, srcTableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dstOffset, srcOffset, length, dstTableIndex, srcTableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dstOffset, VirtualRegister& srcOffset, VirtualRegister& length, unsigned& dstTableIndex, unsigned& srcTableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dstOffset)
            && Fits<VirtualRegister, __size>::check(srcOffset)
            && Fits<VirtualRegister, __size>::check(length)
            && Fits<unsigned, __size>::check(dstTableIndex)
            && Fits<unsigned, __size>::check(srcTableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dstOffset, VirtualRegister srcOffset, VirtualRegister length, unsigned dstTableIndex, unsigned srcTableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dstOffset, srcOffset, length, dstTableIndex, srcTableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dstOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(srcOffset));
            gen->write(Fits<VirtualRegister, __size>::convert(length));
            gen->write(Fits<unsigned, __size>::convert(dstTableIndex));
            gen->write(Fits<unsigned, __size>::convert(srcTableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**table_copy"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dstOffset", m_dstOffset, true);
        dumper->dumpOperand("srcOffset", m_srcOffset, false);
        dumper->dumpOperand("length", m_length, false);
        dumper->dumpOperand("dstTableIndex", m_dstTableIndex, false);
        dumper->dumpOperand("srcTableIndex", m_srcTableIndex, false);
    }

    WasmTableCopy(const uint8_t* stream)
        : m_dstOffset(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_srcOffset(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_dstTableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_srcTableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmTableCopy(const uint16_t* stream)
        : m_dstOffset(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_srcOffset(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_dstTableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_srcTableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmTableCopy(const uint32_t* stream)
        : m_dstOffset(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_srcOffset(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_dstTableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_srcTableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmTableCopy decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDstOffset(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDstOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDstOffset<OpcodeSize::Wide16>(value, func);
        else
            setDstOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDstOffset(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrcOffset(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSrcOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSrcOffset<OpcodeSize::Wide16>(value, func);
        else
            setSrcOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcOffset(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLength<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLength<OpcodeSize::Wide16>(value, func);
        else
            setLength<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setDstTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDstTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDstTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setDstTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDstTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setSrcTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSrcTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSrcTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setSrcTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dstOffset;
    VirtualRegister m_srcOffset;
    VirtualRegister m_length;
    unsigned m_dstTableIndex;
    unsigned m_srcTableIndex;
};


struct WasmCall : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, functionIndex, stackOffset, numberOfStackArgs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, functionIndex, stackOffset, numberOfStackArgs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, functionIndex, stackOffset, numberOfStackArgs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, functionIndex, stackOffset, numberOfStackArgs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, functionIndex, stackOffset, numberOfStackArgs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& functionIndex, unsigned& stackOffset, unsigned& numberOfStackArgs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(functionIndex)
            && Fits<unsigned, __size>::check(stackOffset)
            && Fits<unsigned, __size>::check(numberOfStackArgs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, functionIndex, stackOffset, numberOfStackArgs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(functionIndex));
            gen->write(Fits<unsigned, __size>::convert(stackOffset));
            gen->write(Fits<unsigned, __size>::convert(numberOfStackArgs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("functionIndex", m_functionIndex, true);
        dumper->dumpOperand("stackOffset", m_stackOffset, false);
        dumper->dumpOperand("numberOfStackArgs", m_numberOfStackArgs, false);
    }

    WasmCall(const uint8_t* stream)
        : m_functionIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCall(const uint16_t* stream)
        : m_functionIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCall(const uint32_t* stream)
        : m_functionIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCall decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setFunctionIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide16>(value, func);
        else
            setFunctionIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide16>(value, func);
        else
            setStackOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide16>(value, func);
        else
            setNumberOfStackArgs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    unsigned m_functionIndex;
    unsigned m_stackOffset;
    unsigned m_numberOfStackArgs;
};


struct WasmCallNoTls : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_no_tls;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, functionIndex, stackOffset, numberOfStackArgs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, functionIndex, stackOffset, numberOfStackArgs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, functionIndex, stackOffset, numberOfStackArgs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, functionIndex, stackOffset, numberOfStackArgs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, functionIndex, stackOffset, numberOfStackArgs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& functionIndex, unsigned& stackOffset, unsigned& numberOfStackArgs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(functionIndex)
            && Fits<unsigned, __size>::check(stackOffset)
            && Fits<unsigned, __size>::check(numberOfStackArgs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned functionIndex, unsigned stackOffset, unsigned numberOfStackArgs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, functionIndex, stackOffset, numberOfStackArgs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(functionIndex));
            gen->write(Fits<unsigned, __size>::convert(stackOffset));
            gen->write(Fits<unsigned, __size>::convert(numberOfStackArgs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_no_tls"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("functionIndex", m_functionIndex, true);
        dumper->dumpOperand("stackOffset", m_stackOffset, false);
        dumper->dumpOperand("numberOfStackArgs", m_numberOfStackArgs, false);
    }

    WasmCallNoTls(const uint8_t* stream)
        : m_functionIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallNoTls(const uint16_t* stream)
        : m_functionIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallNoTls(const uint32_t* stream)
        : m_functionIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallNoTls decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setFunctionIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide16>(value, func);
        else
            setFunctionIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide16>(value, func);
        else
            setStackOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide16>(value, func);
        else
            setNumberOfStackArgs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    unsigned m_functionIndex;
    unsigned m_stackOffset;
    unsigned m_numberOfStackArgs;
};


struct WasmCallIndirect : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_indirect;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& functionIndex, unsigned& signatureIndex, unsigned& stackOffset, unsigned& numberOfStackArgs, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(functionIndex)
            && Fits<unsigned, __size>::check(signatureIndex)
            && Fits<unsigned, __size>::check(stackOffset)
            && Fits<unsigned, __size>::check(numberOfStackArgs)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(functionIndex));
            gen->write(Fits<unsigned, __size>::convert(signatureIndex));
            gen->write(Fits<unsigned, __size>::convert(stackOffset));
            gen->write(Fits<unsigned, __size>::convert(numberOfStackArgs));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_indirect"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("functionIndex", m_functionIndex, true);
        dumper->dumpOperand("signatureIndex", m_signatureIndex, false);
        dumper->dumpOperand("stackOffset", m_stackOffset, false);
        dumper->dumpOperand("numberOfStackArgs", m_numberOfStackArgs, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmCallIndirect(const uint8_t* stream)
        : m_functionIndex(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_signatureIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallIndirect(const uint16_t* stream)
        : m_functionIndex(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_signatureIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallIndirect(const uint32_t* stream)
        : m_functionIndex(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_signatureIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallIndirect decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setFunctionIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide16>(value, func);
        else
            setFunctionIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSignatureIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSignatureIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSignatureIndex<OpcodeSize::Wide16>(value, func);
        else
            setSignatureIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSignatureIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide16>(value, func);
        else
            setStackOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide16>(value, func);
        else
            setNumberOfStackArgs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_functionIndex;
    unsigned m_signatureIndex;
    unsigned m_stackOffset;
    unsigned m_numberOfStackArgs;
    unsigned m_tableIndex;
};


struct WasmCallIndirectNoTls : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_call_indirect_no_tls;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& functionIndex, unsigned& signatureIndex, unsigned& stackOffset, unsigned& numberOfStackArgs, unsigned& tableIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(functionIndex)
            && Fits<unsigned, __size>::check(signatureIndex)
            && Fits<unsigned, __size>::check(stackOffset)
            && Fits<unsigned, __size>::check(numberOfStackArgs)
            && Fits<unsigned, __size>::check(tableIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister functionIndex, unsigned signatureIndex, unsigned stackOffset, unsigned numberOfStackArgs, unsigned tableIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, functionIndex, signatureIndex, stackOffset, numberOfStackArgs, tableIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(functionIndex));
            gen->write(Fits<unsigned, __size>::convert(signatureIndex));
            gen->write(Fits<unsigned, __size>::convert(stackOffset));
            gen->write(Fits<unsigned, __size>::convert(numberOfStackArgs));
            gen->write(Fits<unsigned, __size>::convert(tableIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_indirect_no_tls"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("functionIndex", m_functionIndex, true);
        dumper->dumpOperand("signatureIndex", m_signatureIndex, false);
        dumper->dumpOperand("stackOffset", m_stackOffset, false);
        dumper->dumpOperand("numberOfStackArgs", m_numberOfStackArgs, false);
        dumper->dumpOperand("tableIndex", m_tableIndex, false);
    }

    WasmCallIndirectNoTls(const uint8_t* stream)
        : m_functionIndex(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_signatureIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCallIndirectNoTls(const uint16_t* stream)
        : m_functionIndex(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_signatureIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCallIndirectNoTls(const uint32_t* stream)
        : m_functionIndex(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_signatureIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_stackOffset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_numberOfStackArgs(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCallIndirectNoTls decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setFunctionIndex(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setFunctionIndex<OpcodeSize::Wide16>(value, func);
        else
            setFunctionIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setFunctionIndex(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSignatureIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSignatureIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSignatureIndex<OpcodeSize::Wide16>(value, func);
        else
            setSignatureIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSignatureIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setStackOffset<OpcodeSize::Wide16>(value, func);
        else
            setStackOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setStackOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setNumberOfStackArgs<OpcodeSize::Wide16>(value, func);
        else
            setNumberOfStackArgs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNumberOfStackArgs(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTableIndex<OpcodeSize::Wide16>(value, func);
        else
            setTableIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_functionIndex;
    unsigned m_signatureIndex;
    unsigned m_stackOffset;
    unsigned m_numberOfStackArgs;
    unsigned m_tableIndex;
};


struct WasmCurrentMemory : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_current_memory;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**current_memory"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
    }

    WasmCurrentMemory(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmCurrentMemory(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmCurrentMemory(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmCurrentMemory decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
};


struct WasmGrowMemory : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_grow_memory;
    static constexpr size_t length = 3;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister delta)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, delta);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister delta)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, delta);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister delta)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, delta))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, delta))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, delta);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& delta)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(delta)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister delta)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, delta)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(delta));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**grow_memory"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("delta", m_delta, false);
    }

    WasmGrowMemory(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_delta(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmGrowMemory(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_delta(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmGrowMemory(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_delta(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmGrowMemory decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setDelta(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDelta<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDelta<OpcodeSize::Wide16>(value, func);
        else
            setDelta<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDelta(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_delta;
};


struct WasmMemoryFill : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_memory_fill;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister targetValue, VirtualRegister count)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dstAddress, targetValue, count);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister targetValue, VirtualRegister count)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dstAddress, targetValue, count);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister targetValue, VirtualRegister count)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dstAddress, targetValue, count))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dstAddress, targetValue, count))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dstAddress, targetValue, count);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dstAddress, VirtualRegister& targetValue, VirtualRegister& count)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dstAddress)
            && Fits<VirtualRegister, __size>::check(targetValue)
            && Fits<VirtualRegister, __size>::check(count)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister targetValue, VirtualRegister count)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dstAddress, targetValue, count)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dstAddress));
            gen->write(Fits<VirtualRegister, __size>::convert(targetValue));
            gen->write(Fits<VirtualRegister, __size>::convert(count));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**memory_fill"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dstAddress", m_dstAddress, true);
        dumper->dumpOperand("targetValue", m_targetValue, false);
        dumper->dumpOperand("count", m_count, false);
    }

    WasmMemoryFill(const uint8_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_targetValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMemoryFill(const uint16_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_targetValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMemoryFill(const uint32_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_targetValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMemoryFill decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDstAddress(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDstAddress<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDstAddress<OpcodeSize::Wide16>(value, func);
        else
            setDstAddress<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDstAddress(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTargetValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTargetValue<OpcodeSize::Wide16>(value, func);
        else
            setTargetValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTargetValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCount(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setCount<OpcodeSize::Wide16>(value, func);
        else
            setCount<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCount(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dstAddress;
    VirtualRegister m_targetValue;
    VirtualRegister m_count;
};


struct WasmMemoryCopy : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_memory_copy;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister count)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dstAddress, srcAddress, count);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister count)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dstAddress, srcAddress, count);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister count)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dstAddress, srcAddress, count))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dstAddress, srcAddress, count))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dstAddress, srcAddress, count);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dstAddress, VirtualRegister& srcAddress, VirtualRegister& count)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dstAddress)
            && Fits<VirtualRegister, __size>::check(srcAddress)
            && Fits<VirtualRegister, __size>::check(count)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister count)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dstAddress, srcAddress, count)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dstAddress));
            gen->write(Fits<VirtualRegister, __size>::convert(srcAddress));
            gen->write(Fits<VirtualRegister, __size>::convert(count));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**memory_copy"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dstAddress", m_dstAddress, true);
        dumper->dumpOperand("srcAddress", m_srcAddress, false);
        dumper->dumpOperand("count", m_count, false);
    }

    WasmMemoryCopy(const uint8_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_srcAddress(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMemoryCopy(const uint16_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_srcAddress(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMemoryCopy(const uint32_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_srcAddress(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMemoryCopy decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDstAddress(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDstAddress<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDstAddress<OpcodeSize::Wide16>(value, func);
        else
            setDstAddress<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDstAddress(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrcAddress(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSrcAddress<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSrcAddress<OpcodeSize::Wide16>(value, func);
        else
            setSrcAddress<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcAddress(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCount(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setCount<OpcodeSize::Wide16>(value, func);
        else
            setCount<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCount(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dstAddress;
    VirtualRegister m_srcAddress;
    VirtualRegister m_count;
};


struct WasmMemoryInit : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_memory_init;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister length, unsigned dataSegmentIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dstAddress, srcAddress, length, dataSegmentIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister length, unsigned dataSegmentIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dstAddress, srcAddress, length, dataSegmentIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister length, unsigned dataSegmentIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dstAddress, srcAddress, length, dataSegmentIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dstAddress, srcAddress, length, dataSegmentIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dstAddress, srcAddress, length, dataSegmentIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dstAddress, VirtualRegister& srcAddress, VirtualRegister& length, unsigned& dataSegmentIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dstAddress)
            && Fits<VirtualRegister, __size>::check(srcAddress)
            && Fits<VirtualRegister, __size>::check(length)
            && Fits<unsigned, __size>::check(dataSegmentIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dstAddress, VirtualRegister srcAddress, VirtualRegister length, unsigned dataSegmentIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dstAddress, srcAddress, length, dataSegmentIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dstAddress));
            gen->write(Fits<VirtualRegister, __size>::convert(srcAddress));
            gen->write(Fits<VirtualRegister, __size>::convert(length));
            gen->write(Fits<unsigned, __size>::convert(dataSegmentIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**memory_init"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dstAddress", m_dstAddress, true);
        dumper->dumpOperand("srcAddress", m_srcAddress, false);
        dumper->dumpOperand("length", m_length, false);
        dumper->dumpOperand("dataSegmentIndex", m_dataSegmentIndex, false);
    }

    WasmMemoryInit(const uint8_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_srcAddress(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_dataSegmentIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMemoryInit(const uint16_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_srcAddress(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_dataSegmentIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMemoryInit(const uint32_t* stream)
        : m_dstAddress(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_srcAddress(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_length(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_dataSegmentIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMemoryInit decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDstAddress(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDstAddress<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDstAddress<OpcodeSize::Wide16>(value, func);
        else
            setDstAddress<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDstAddress(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSrcAddress(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setSrcAddress<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setSrcAddress<OpcodeSize::Wide16>(value, func);
        else
            setSrcAddress<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setSrcAddress(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLength<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLength<OpcodeSize::Wide16>(value, func);
        else
            setLength<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setDataSegmentIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDataSegmentIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDataSegmentIndex<OpcodeSize::Wide16>(value, func);
        else
            setDataSegmentIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDataSegmentIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dstAddress;
    VirtualRegister m_srcAddress;
    VirtualRegister m_length;
    unsigned m_dataSegmentIndex;
};


struct WasmDataDrop : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_data_drop;
    static constexpr size_t length = 2;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, unsigned dataSegmentIndex)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dataSegmentIndex);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned dataSegmentIndex)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dataSegmentIndex);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, unsigned dataSegmentIndex)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dataSegmentIndex))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dataSegmentIndex))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dataSegmentIndex);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, unsigned& dataSegmentIndex)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<unsigned, __size>::check(dataSegmentIndex)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, unsigned dataSegmentIndex)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dataSegmentIndex)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<unsigned, __size>::convert(dataSegmentIndex));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**data_drop"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dataSegmentIndex", m_dataSegmentIndex, true);
    }

    WasmDataDrop(const uint8_t* stream)
        : m_dataSegmentIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmDataDrop(const uint16_t* stream)
        : m_dataSegmentIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmDataDrop(const uint32_t* stream)
        : m_dataSegmentIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[0]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmDataDrop decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDataSegmentIndex(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDataSegmentIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDataSegmentIndex<OpcodeSize::Wide16>(value, func);
        else
            setDataSegmentIndex<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDataSegmentIndex(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    unsigned m_dataSegmentIndex;
};


struct WasmSelect : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_select;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister condition, VirtualRegister nonZero, VirtualRegister zero)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, condition, nonZero, zero);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister condition, VirtualRegister nonZero, VirtualRegister zero)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, condition, nonZero, zero);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister condition, VirtualRegister nonZero, VirtualRegister zero)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, condition, nonZero, zero))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, condition, nonZero, zero))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, condition, nonZero, zero);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& condition, VirtualRegister& nonZero, VirtualRegister& zero)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(condition)
            && Fits<VirtualRegister, __size>::check(nonZero)
            && Fits<VirtualRegister, __size>::check(zero)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister condition, VirtualRegister nonZero, VirtualRegister zero)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, condition, nonZero, zero)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(condition));
            gen->write(Fits<VirtualRegister, __size>::convert(nonZero));
            gen->write(Fits<VirtualRegister, __size>::convert(zero));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**select"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("condition", m_condition, false);
        dumper->dumpOperand("nonZero", m_nonZero, false);
        dumper->dumpOperand("zero", m_zero, false);
    }

    WasmSelect(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_nonZero(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_zero(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmSelect(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_nonZero(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_zero(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmSelect(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_nonZero(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_zero(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmSelect decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setCondition<OpcodeSize::Wide16>(value, func);
        else
            setCondition<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNonZero(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setNonZero<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setNonZero<OpcodeSize::Wide16>(value, func);
        else
            setNonZero<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setNonZero(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setZero(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setZero<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setZero<OpcodeSize::Wide16>(value, func);
        else
            setZero<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setZero(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_condition;
    VirtualRegister m_nonZero;
    VirtualRegister m_zero;
};


struct WasmLoad8U : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_load8_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**load8_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmLoad8U(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmLoad8U(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmLoad8U(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmLoad8U decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmLoad16U : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_load16_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**load16_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmLoad16U(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmLoad16U(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmLoad16U(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmLoad16U decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmLoad32U : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_load32_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**load32_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmLoad32U(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmLoad32U(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmLoad32U(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmLoad32U decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmLoad64U : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_load64_u;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**load64_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmLoad64U(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmLoad64U(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmLoad64U(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmLoad64U decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmI32Load8S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_load8_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_load8_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmI32Load8S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Load8S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Load8S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Load8S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmI64Load8S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_load8_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_load8_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmI64Load8S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Load8S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Load8S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Load8S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmI32Load16S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_load16_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_load16_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmI32Load16S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Load16S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Load16S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Load16S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmI64Load16S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_load16_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_load16_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmI64Load16S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Load16S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Load16S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Load16S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmI64Load32S : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_load32_s;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_load32_s"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmI64Load32S(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64Load32S(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64Load32S(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64Load32S decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
};


struct WasmStore8 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_store8;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, pointer, value, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, pointer, value, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, pointer, value, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& pointer, VirtualRegister& value, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, pointer, value, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**store8"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("pointer", m_pointer, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmStore8(const uint8_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmStore8(const uint16_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmStore8(const uint32_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmStore8 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_pointer;
    VirtualRegister m_value;
    unsigned m_offset;
};


struct WasmStore16 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_store16;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, pointer, value, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, pointer, value, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, pointer, value, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& pointer, VirtualRegister& value, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, pointer, value, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**store16"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("pointer", m_pointer, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmStore16(const uint8_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmStore16(const uint16_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmStore16(const uint32_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmStore16 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_pointer;
    VirtualRegister m_value;
    unsigned m_offset;
};


struct WasmStore32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_store32;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, pointer, value, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, pointer, value, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, pointer, value, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& pointer, VirtualRegister& value, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, pointer, value, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**store32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("pointer", m_pointer, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmStore32(const uint8_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmStore32(const uint16_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmStore32(const uint32_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmStore32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_pointer;
    VirtualRegister m_value;
    unsigned m_offset;
};


struct WasmStore64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_store64;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, pointer, value, offset);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, pointer, value, offset);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, pointer, value, offset))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, pointer, value, offset);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& pointer, VirtualRegister& value, unsigned& offset)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<unsigned, __size>::check(offset)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister pointer, VirtualRegister value, unsigned offset)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, pointer, value, offset)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<unsigned, __size>::convert(offset));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**store64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("pointer", m_pointer, true);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("offset", m_offset, false);
    }

    WasmStore64(const uint8_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmStore64(const uint16_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmStore64(const uint32_t* stream)
        : m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmStore64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_pointer;
    VirtualRegister m_value;
    unsigned m_offset;
};


struct WasmI64AtomicRmwAdd : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_add;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwAdd(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwAdd(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwAdd(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwAdd decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8AddU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_add_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_add_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8AddU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8AddU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8AddU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8AddU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16AddU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_add_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_add_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16AddU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16AddU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16AddU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16AddU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32AddU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_add_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_add_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32AddU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32AddU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32AddU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32AddU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmwSub : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_sub;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwSub(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwSub(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwSub(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwSub decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8SubU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_sub_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_sub_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8SubU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8SubU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8SubU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8SubU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16SubU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_sub_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_sub_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16SubU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16SubU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16SubU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16SubU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32SubU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_sub_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_sub_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32SubU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32SubU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32SubU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32SubU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmwAnd : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_and;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_and"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwAnd(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwAnd(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwAnd(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwAnd decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8AndU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_and_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_and_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8AndU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8AndU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8AndU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8AndU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16AndU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_and_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_and_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16AndU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16AndU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16AndU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16AndU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32AndU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_and_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_and_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32AndU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32AndU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32AndU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32AndU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmwOr : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_or;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_or"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwOr(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwOr(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwOr(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwOr decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8OrU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_or_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_or_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8OrU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8OrU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8OrU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8OrU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16OrU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_or_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_or_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16OrU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16OrU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16OrU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16OrU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32OrU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_or_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_or_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32OrU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32OrU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32OrU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32OrU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmwXor : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_xor;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_xor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwXor(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwXor(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwXor(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwXor decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8XorU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_xor_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_xor_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8XorU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8XorU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8XorU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8XorU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16XorU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_xor_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_xor_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16XorU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16XorU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16XorU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16XorU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32XorU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_xor_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_xor_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32XorU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32XorU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32XorU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32XorU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmwXchg : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_xchg;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_xchg"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwXchg(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwXchg(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwXchg(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwXchg decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8XchgU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_xchg_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_xchg_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8XchgU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8XchgU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8XchgU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8XchgU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16XchgU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_xchg_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_xchg_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16XchgU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16XchgU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16XchgU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16XchgU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32XchgU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_xchg_u;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_xchg_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32XchgU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32XchgU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32XchgU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32XchgU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmwCmpxchg : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw_cmpxchg;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, expected, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& expected, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(expected)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, expected, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(expected));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw_cmpxchg"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("expected", m_expected, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmwCmpxchg(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmwCmpxchg(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmwCmpxchg(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmwCmpxchg decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide16>(value, func);
        else
            setExpected<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_expected;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw8CmpxchgU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw8_cmpxchg_u;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, expected, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& expected, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(expected)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, expected, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(expected));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw8_cmpxchg_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("expected", m_expected, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw8CmpxchgU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw8CmpxchgU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw8CmpxchgU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw8CmpxchgU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide16>(value, func);
        else
            setExpected<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_expected;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw16CmpxchgU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw16_cmpxchg_u;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, expected, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& expected, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(expected)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, expected, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(expected));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw16_cmpxchg_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("expected", m_expected, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw16CmpxchgU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw16CmpxchgU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw16CmpxchgU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw16CmpxchgU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide16>(value, func);
        else
            setExpected<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_expected;
    VirtualRegister m_value;
};


struct WasmI64AtomicRmw32CmpxchgU : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i64_atomic_rmw32_cmpxchg_u;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, expected, value);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, expected, value))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, expected, value);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& expected, VirtualRegister& value)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(expected)
            && Fits<VirtualRegister, __size>::check(value)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister expected, VirtualRegister value)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, expected, value)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(expected));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i64_atomic_rmw32_cmpxchg_u"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("expected", m_expected, false);
        dumper->dumpOperand("value", m_value, false);
    }

    WasmI64AtomicRmw32CmpxchgU(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI64AtomicRmw32CmpxchgU(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI64AtomicRmw32CmpxchgU(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_expected(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI64AtomicRmw32CmpxchgU decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setExpected<OpcodeSize::Wide16>(value, func);
        else
            setExpected<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setExpected(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_expected;
    VirtualRegister m_value;
};


struct WasmMemoryAtomicWait32 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_memory_atomic_wait32;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value, timeout);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value, timeout);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value, timeout))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value, timeout))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value, timeout);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value, VirtualRegister& timeout)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(timeout)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value, timeout)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(timeout));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**memory_atomic_wait32"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("timeout", m_timeout, false);
    }

    WasmMemoryAtomicWait32(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_timeout(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMemoryAtomicWait32(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_timeout(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMemoryAtomicWait32(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_timeout(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMemoryAtomicWait32 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTimeout(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTimeout<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTimeout<OpcodeSize::Wide16>(value, func);
        else
            setTimeout<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTimeout(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
    VirtualRegister m_timeout;
};


struct WasmMemoryAtomicWait64 : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_memory_atomic_wait64;
    static constexpr size_t length = 6;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, value, timeout);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, value, timeout);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value, timeout))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, value, timeout))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, value, timeout);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& value, VirtualRegister& timeout)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(value)
            && Fits<VirtualRegister, __size>::check(timeout)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister value, VirtualRegister timeout)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, value, timeout)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(value));
            gen->write(Fits<VirtualRegister, __size>::convert(timeout));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**memory_atomic_wait64"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("value", m_value, false);
        dumper->dumpOperand("timeout", m_timeout, false);
    }

    WasmMemoryAtomicWait64(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_timeout(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMemoryAtomicWait64(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_timeout(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMemoryAtomicWait64(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_timeout(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMemoryAtomicWait64 decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setValue<OpcodeSize::Wide16>(value, func);
        else
            setValue<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTimeout(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setTimeout<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setTimeout<OpcodeSize::Wide16>(value, func);
        else
            setTimeout<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setTimeout(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 4 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_value;
    VirtualRegister m_timeout;
};


struct WasmMemoryAtomicNotify : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_memory_atomic_notify;
    static constexpr size_t length = 5;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister count)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, pointer, offset, count);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister count)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, pointer, offset, count);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister count)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, count))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, pointer, offset, count))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, pointer, offset, count);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& pointer, unsigned& offset, VirtualRegister& count)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(pointer)
            && Fits<unsigned, __size>::check(offset)
            && Fits<VirtualRegister, __size>::check(count)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister pointer, unsigned offset, VirtualRegister count)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, pointer, offset, count)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(pointer));
            gen->write(Fits<unsigned, __size>::convert(offset));
            gen->write(Fits<VirtualRegister, __size>::convert(count));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**memory_atomic_notify"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("pointer", m_pointer, false);
        dumper->dumpOperand("offset", m_offset, false);
        dumper->dumpOperand("count", m_count, false);
    }

    WasmMemoryAtomicNotify(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmMemoryAtomicNotify(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmMemoryAtomicNotify(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_pointer(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_count(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmMemoryAtomicNotify decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setPointer<OpcodeSize::Wide16>(value, func);
        else
            setPointer<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setPointer(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setOffset<OpcodeSize::Wide16>(value, func);
        else
            setOffset<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (!Fits<unsigned, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setCount(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setCount<OpcodeSize::Wide16>(value, func);
        else
            setCount<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setCount(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 3 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_pointer;
    unsigned m_offset;
    VirtualRegister m_count;
};


struct WasmI32Add : public Instruction {
    static constexpr WasmOpcodeID opcodeID = wasm_i32_add;
    static constexpr size_t length = 4;
    
    


    template<typename BytecodeGenerator>
    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow, BytecodeGenerator>(gen, dst, lhs, rhs);
    }

    template<OpcodeSize __size, typename BytecodeGenerator, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        bool didEmit = emitImpl<__size, recordOpcode, BytecodeGenerator>(gen, dst, lhs, rhs);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize __size, typename BytecodeGenerator>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(__size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, BytecodeGenerator, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, BytecodeGenerator, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize __size, typename BytecodeGenerator>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& lhs, VirtualRegister& rhs)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: Disable wide16 optimization for Windows CLoop
        // https://bugs.webkit.org/show_bug.cgi?id=198283
        if (__size == OpcodeSize::Wide16)
            return false;
#endif
        return Fits<WasmOpcodeID, __size>::check(opcodeID)
            && Fits<VirtualRegister, __size>::check(dst)
            && Fits<VirtualRegister, __size>::check(lhs)
            && Fits<VirtualRegister, __size>::check(rhs)
            && (__size == OpcodeSize::Wide16 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide16) : true)
            && (__size == OpcodeSize::Wide32 ? Fits<WasmOpcodeID, OpcodeSize::Narrow>::check(wasm_wide32) : true);
    }

    template<OpcodeSize __size, bool recordOpcode, typename BytecodeGenerator>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        
        if (__size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (__size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<__size>(gen, dst, lhs, rhs)) {
            if (recordOpcode)
                gen->recordOpcode(opcodeID);
            if (__size == OpcodeSize::Wide16)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide16));
            else if (__size == OpcodeSize::Wide32)
                gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(wasm_wide32));
            gen->write(Fits<WasmOpcodeID, OpcodeSize::Narrow>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, __size>::convert(dst));
            gen->write(Fits<VirtualRegister, __size>::convert(lhs));
            gen->write(Fits<VirtualRegister, __size>::convert(rhs));
            return true;
        }
        return false;
    }

public:
    void dump(BytecodeDumperBase* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**i32_add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand("dst", m_dst, true);
        dumper->dumpOperand("lhs", m_lhs, false);
        dumper->dumpOperand("rhs", m_rhs, false);
    }

    WasmI32Add(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    WasmI32Add(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }


    WasmI32Add(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[0]))
        , m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, bitwise_cast<const uint8_t*>(stream)[-1] == opcodeID);
    }

    static WasmI32Add decode(const uint8_t* stream)
    {
        // A pointer is pointing to the first operand (opcode and prefix are not included).
        if (*stream == wasm_wide32)
            return { bitwise_cast<const uint32_t*>(stream + 2) };
        if (*stream == wasm_wide16)
            return { bitwise_cast<const uint16_t*>(stream + 2) };
        return { stream + 1 };
    }

    template<typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setDst<OpcodeSize::Wide16>(value, func);
        else
            setDst<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setDst(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 0 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setLhs<OpcodeSize::Wide16>(value, func);
        else
            setLhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 1 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16<WasmOpcodeTraits>())
            setRhs<OpcodeSize::Wide16>(value, func);
        else
            setRhs<OpcodeSize::Narrow>(value, func);
    }

    template <OpcodeSize size, typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (!Fits<VirtualRegister, size>::check(value))
            value = func();
        auto* stream = bitwise_cast<typename TypeBySize<size>::unsignedType*>(reinterpret_cast<uint8_t*>(this) + 2 * size + PaddingBySize<size>::value + /* Opcode size */ 1);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};


#endif // ENABLE(WEBASSEMBLY)

} // namespace JSC
//  SHA1Hash: a76f4e6da941f840c6fa40e2cfc17431f4a02ca8