//  SHA1Hash: da39a3ee5e6b4b0d3255bfef95601890afd80709
/*
 * Copyright (C) 2021 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 from C:/Users/admin/dev/Jenkins/workspace/WebCore_master/Source/JavaScriptCore/bytecode/BytecodeList.rb, do not modify.
*/

#pragma once

#include "ArithProfile.h"
#include "BytecodeDumper.h"
#include "BytecodeGenerator.h"
#include "Fits.h"
#include "GetByIdMetadata.h"
#include "Instruction.h"
#include "Opcode.h"
#include "PutByIdStatus.h"
#include "PutByIdFlags.h"
#include "ToThisStatus.h"

namespace JSC {

struct OpTailCallVarargs : public Instruction {
    static constexpr OpcodeID opcodeID = op_tail_call_varargs;

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

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size>
    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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, 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, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**tail_call_varargs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_arguments, false);
        dumper->dumpOperand(m_firstFree, false);
        dumper->dumpOperand(m_firstVarArg, false);
    }

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

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


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

    static OpTailCallVarargs decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 6 * size + PaddingBySize<size>::value);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpTailCallVarargs&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpGetDirectPname : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_direct_pname;

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

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, base, property, index, enumerator, __metadataID);
    }

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

    template<OpcodeSize size, 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>(gen, dst, base, property, index, enumerator, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, index, enumerator, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, index, enumerator, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_direct_pname"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_index, false);
        dumper->dumpOperand(m_enumerator, false);
    }

    OpGetDirectPname(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetDirectPname(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetDirectPname(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetDirectPname decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetDirectPname&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpHasIndexedProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_indexed_property;

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_indexed_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

    OpHasIndexedProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    OpHasIndexedProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }


    OpHasIndexedProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    static OpHasIndexedProperty decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpHasIndexedProperty&) { }

        ArrayProfile m_arrayProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, textOffset, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, textOffset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, textOffset, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<int, size>::convert(textOffset));
            gen->write(Fits<unsigned, size>::convert(__metadataID));
            return true;
        }
        return false;
    }

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

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

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


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

    static OpProfileControlFlow decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTextOffset(int value, Functor func)
    {
        if (isWide32())
            setTextOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpProfileControlFlow&) { }

        BasicBlockLocation* m_basicBlockLocation;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    int m_textOffset;
    unsigned m_metadataID;
};

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

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

    template<OpcodeSize size, 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, shouldAssert>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
    }

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

    template<OpcodeSize size, 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>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, targetVirtualRegister, symbolTableOrScopeDepth, flag, identifier, resolveType, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**profile_type"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_targetVirtualRegister, true);
        dumper->dumpOperand(m_symbolTableOrScopeDepth, false);
        dumper->dumpOperand(m_flag, false);
        dumper->dumpOperand(m_identifier, false);
        dumper->dumpOperand(m_resolveType, false);
    }

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

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


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

    static OpProfileType decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTargetVirtualRegister(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setTargetVirtualRegister<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
    {
        if (isWide32())
            setSymbolTableOrScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value);
    }

    template<typename Functor>
    void setFlag(ProfileTypeBytecodeFlag value, Functor func)
    {
        if (isWide32())
            setFlag<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<ProfileTypeBytecodeFlag, size>::convert(value);
    }

    template<typename Functor>
    void setIdentifier(unsigned value, Functor func)
    {
        if (isWide32())
            setIdentifier<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setResolveType(ResolveType value, Functor func)
    {
        if (isWide32())
            setResolveType<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<ResolveType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpProfileType&) { }

        TypeLocation* m_typeLocation;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpCatch : public Instruction {
    static constexpr OpcodeID opcodeID = op_catch;

    static void emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, exception, thrownValue);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert>
    static bool emit(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        auto __metadataID = gen->addMetadataFor(opcodeID);
        return emit<size, shouldAssert>(gen, exception, thrownValue, __metadataID);
    }

    template<OpcodeSize size>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister exception, VirtualRegister thrownValue)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<size>(gen, exception, thrownValue, __metadataID);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, exception, thrownValue, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, exception, thrownValue, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, exception, thrownValue, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**catch"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_exception, true);
        dumper->dumpOperand(m_thrownValue, false);
    }

    OpCatch(const uint8_t* stream)
        : m_exception(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCatch(const uint16_t* stream)
        : m_exception(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCatch(const uint32_t* stream)
        : m_exception(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_thrownValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCatch decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setException(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setException<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThrownValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThrownValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpCatch&) { }

        ValueProfileAndOperandBuffer* m_buffer;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_exception;
    VirtualRegister m_thrownValue;
    unsigned m_metadataID;
};

struct OpGetFromArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_from_arguments;

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, arguments, index, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, arguments, index, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, arguments, index, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_from_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_arguments, false);
        dumper->dumpOperand(m_index, false);
    }

    OpGetFromArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetFromArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetFromArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetFromArguments decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetFromArguments&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_arguments;
    unsigned m_index;
    unsigned m_metadataID;
};

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, inlineCapacity, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, inlineCapacity, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_inlineCapacity, false);
    }

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

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


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

    static OpCreateThis decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInlineCapacity(unsigned value, Functor func)
    {
        if (isWide32())
            setInlineCapacity<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpCreateThis&) { }

        WriteBarrier<JSCell> m_cachedCallee;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, index, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, index, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, index, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_argument"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_index, false);
    }

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

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


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

    static OpGetArgument decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setIndex(int value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetArgument&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    int m_index;
    unsigned m_metadataID;
};

struct OpPutToScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_to_scope;

    static void emit(BytecodeGenerator* gen, VirtualRegister scope, unsigned var, VirtualRegister value, GetPutInfo getPutInfo, SymbolTableOrScopeDepth symbolTableOrScopeDepth, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset);
    }

    template<OpcodeSize size, 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, shouldAssert>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize size>
    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>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, 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, NoAssert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, scope, var, value, getPutInfo, symbolTableOrScopeDepth, offset, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_to_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_scope, true);
        dumper->dumpOperand(m_var, false);
        dumper->dumpOperand(m_value, false);
        dumper->dumpOperand(m_getPutInfo, false);
        dumper->dumpOperand(m_symbolTableOrScopeDepth, false);
        dumper->dumpOperand(m_offset, false);
    }

    OpPutToScope(const uint8_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[4]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Narrow>::convert(stream[5]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutToScope(const uint16_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide16>::convert(stream[4]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide16>::convert(stream[5]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutToScope(const uint32_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide32>::convert(stream[4]))
        , m_symbolTableOrScopeDepth(Fits<SymbolTableOrScopeDepth, OpcodeSize::Wide32>::convert(stream[5]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutToScope decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (isWide32())
            setVar<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setGetPutInfo(GetPutInfo value, Functor func)
    {
        if (isWide32())
            setGetPutInfo<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<GetPutInfo, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTableOrScopeDepth(SymbolTableOrScopeDepth value, Functor func)
    {
        if (isWide32())
            setSymbolTableOrScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<SymbolTableOrScopeDepth, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 6 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        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);
    }

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_scope;
    unsigned m_var;
    VirtualRegister m_value;
    GetPutInfo m_getPutInfo;
    SymbolTableOrScopeDepth m_symbolTableOrScopeDepth;
    unsigned m_offset;
    unsigned m_metadataID;
};

struct OpToThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_this;

    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst);
    }

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, srcDst, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(srcDst));
            gen->write(Fits<unsigned, size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_srcDst, true);
    }

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

    OpToThis(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpToThis(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpToThis decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpToThis&) { }

        StructureID m_cachedStructureID;
        ToThisStatus m_toThisStatus;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_srcDst;
    unsigned m_metadataID;
};

struct OpGetFromScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_from_scope;

    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, GetPutInfo getPutInfo, unsigned localScopeDepth, unsigned offset)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset);
    }

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize size>
    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>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, 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, NoAssert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, var, getPutInfo, localScopeDepth, offset, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_from_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_var, false);
        dumper->dumpOperand(m_getPutInfo, false);
        dumper->dumpOperand(m_localScopeDepth, false);
        dumper->dumpOperand(m_offset, false);
    }

    OpGetFromScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Narrow>::convert(stream[4]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
        , m_offset(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[7]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetFromScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide16>::convert(stream[4]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[7]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetFromScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_getPutInfo(Fits<GetPutInfo, OpcodeSize::Wide32>::convert(stream[4]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
        , m_offset(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[7]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetFromScope decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (isWide32())
            setVar<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setGetPutInfo(GetPutInfo value, Functor func)
    {
        if (isWide32())
            setGetPutInfo<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<GetPutInfo, size>::convert(value);
    }

    template<typename Functor>
    void setLocalScopeDepth(unsigned value, Functor func)
    {
        if (isWide32())
            setLocalScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setOffset(unsigned value, Functor func)
    {
        if (isWide32())
            setOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 6 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        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);
    }

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_var;
    GetPutInfo m_getPutInfo;
    unsigned m_localScopeDepth;
    unsigned m_offset;
    unsigned m_metadataID;
};

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, inlineCapacity, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, inlineCapacity, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, inlineCapacity, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_inlineCapacity, false);
    }

    OpNewObject(const uint8_t* stream)
        : m_dst(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, stream[0] == opcodeID);
    }

    OpNewObject(const uint16_t* stream)
        : m_dst(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, stream[0] == opcodeID);
    }


    OpNewObject(const uint32_t* stream)
        : m_dst(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, stream[0] == opcodeID);
    }

    static OpNewObject decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setInlineCapacity(unsigned value, Functor func)
    {
        if (isWide32())
            setInlineCapacity<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpNewObject&) { }

        ObjectAllocationProfile m_objectAllocationProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    unsigned m_inlineCapacity;
    unsigned m_metadataID;
};

struct OpNewArray : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array;

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

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

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

    template<OpcodeSize size, 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>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, argv, argc, recommendedIndexingType, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_argv, false);
        dumper->dumpOperand(m_argc, false);
        dumper->dumpOperand(m_recommendedIndexingType, false);
    }

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

    OpNewArray(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewArray(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argv(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_argc(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_recommendedIndexingType(Fits<IndexingType, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewArray decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setArgv(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setRecommendedIndexingType(IndexingType value, Functor func)
    {
        if (isWide32())
            setRecommendedIndexingType<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<IndexingType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpNewArray&) { }

        ArrayAllocationProfile m_arrayAllocationProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_argv;
    unsigned m_argc;
    IndexingType m_recommendedIndexingType;
    unsigned m_metadataID;
};

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, length, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, length, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, length, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array_with_size"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_length, false);
    }

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

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


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

    static OpNewArrayWithSize decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLength(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLength<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpNewArrayWithSize&) { }

        ArrayAllocationProfile m_arrayAllocationProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_length;
    unsigned m_metadataID;
};

struct OpNewArrayBuffer : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array_buffer;

    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, immutableButterfly, recommendedIndexingType);
    }

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

    template<OpcodeSize size>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister immutableButterfly, IndexingType recommendedIndexingType)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<size>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, immutableButterfly, recommendedIndexingType, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array_buffer"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_immutableButterfly, false);
        dumper->dumpOperand(m_recommendedIndexingType, false);
    }

    OpNewArrayBuffer(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_immutableButterfly(Fits<VirtualRegister, 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, stream[0] == opcodeID);
    }

    OpNewArrayBuffer(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_immutableButterfly(Fits<VirtualRegister, 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, stream[0] == opcodeID);
    }


    OpNewArrayBuffer(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_immutableButterfly(Fits<VirtualRegister, 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, stream[0] == opcodeID);
    }

    static OpNewArrayBuffer decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setImmutableButterfly(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setImmutableButterfly<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRecommendedIndexingType(IndexingType value, Functor func)
    {
        if (isWide32())
            setRecommendedIndexingType<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<IndexingType, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpNewArrayBuffer&) { }

        ArrayAllocationProfile m_arrayAllocationProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_immutableButterfly;
    IndexingType m_recommendedIndexingType;
    unsigned m_metadataID;
};

struct OpResolveScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_resolve_scope;

    static void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, var, resolveType, localScopeDepth);
    }

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
    }

    template<OpcodeSize size>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned var, ResolveType resolveType, unsigned localScopeDepth)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<size>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, var, resolveType, localScopeDepth, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**resolve_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_var, false);
        dumper->dumpOperand(m_resolveType, false);
        dumper->dumpOperand(m_localScopeDepth, false);
    }

    OpResolveScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_var(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Narrow>::convert(stream[4]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpResolveScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_var(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Wide16>::convert(stream[4]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpResolveScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_var(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_resolveType(Fits<ResolveType, OpcodeSize::Wide32>::convert(stream[4]))
        , m_localScopeDepth(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[6]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpResolveScope decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setVar(unsigned value, Functor func)
    {
        if (isWide32())
            setVar<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setResolveType(ResolveType value, Functor func)
    {
        if (isWide32())
            setResolveType<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<ResolveType, size>::convert(value);
    }

    template<typename Functor>
    void setLocalScopeDepth(unsigned value, Functor func)
    {
        if (isWide32())
            setLocalScopeDepth<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        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);
    }

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_var;
    ResolveType m_resolveType;
    unsigned m_localScopeDepth;
    unsigned m_metadataID;
};

struct OpConstructVarargs : public Instruction {
    static constexpr OpcodeID opcodeID = op_construct_varargs;

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

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size>
    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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, 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, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**construct_varargs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_arguments, false);
        dumper->dumpOperand(m_firstFree, false);
        dumper->dumpOperand(m_firstVarArg, false);
    }

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

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


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

    static OpConstructVarargs decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 6 * size + PaddingBySize<size>::value);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpConstructVarargs&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, argc, argv);
    }

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

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

    template<OpcodeSize size, 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>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**construct"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_argc, false);
        dumper->dumpOperand(m_argv, false);
    }

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

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


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

    static OpConstruct decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpConstruct&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size>
    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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, 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, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**tail_call_forward_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_arguments, false);
        dumper->dumpOperand(m_firstFree, false);
        dumper->dumpOperand(m_firstVarArg, false);
    }

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

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


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

    static OpTailCallForwardArguments decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 6 * size + PaddingBySize<size>::value);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpTailCallForwardArguments&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpCallVarargs : public Instruction {
    static constexpr OpcodeID opcodeID = op_call_varargs;

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

    template<OpcodeSize size, 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, shouldAssert>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size>
    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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, 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, NoAssert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, thisValue, arguments, firstFree, firstVarArg, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_varargs"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_arguments, false);
        dumper->dumpOperand(m_firstFree, false);
        dumper->dumpOperand(m_firstVarArg, false);
    }

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

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


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

    static OpCallVarargs decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstFree(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setFirstFree<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFirstVarArg(int value, Functor func)
    {
        if (isWide32())
            setFirstVarArg<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 6 * size + PaddingBySize<size>::value);
        *stream = Fits<int, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpCallVarargs&) { }

        ArrayProfile m_arrayProfile;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

    template<OpcodeSize size, 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>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call_eval"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_argc, false);
        dumper->dumpOperand(m_argv, false);
    }

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

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


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

    static OpCallEval decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpCallEval&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister callee, unsigned argc, unsigned argv)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, callee, argc, argv);
    }

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

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

    template<OpcodeSize size, 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>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**tail_call"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_argc, false);
        dumper->dumpOperand(m_argv, false);
    }

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

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


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

    static OpTailCall decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpTailCall&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

    template<OpcodeSize size, 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>(gen, dst, callee, argc, argv, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, callee, argc, argv, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, callee, argc, argv, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**call"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_callee, false);
        dumper->dumpOperand(m_argc, false);
        dumper->dumpOperand(m_argv, false);
    }

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

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


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

    static OpCall decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCallee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCallee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgv(unsigned value, Functor func)
    {
        if (isWide32())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpCall&) { }

        LLIntCallLinkInfo m_callLinkInfo;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

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

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& value, Special::Pointer& 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<Special::Pointer, 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister value, Special::Pointer 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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            gen->write(Fits<Special::Pointer, size>::convert(specialPointer));
            gen->write(Fits<BoundLabel, size>::convert(targetLabel));
            gen->write(Fits<unsigned, size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jneq_ptr"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_value, true);
        dumper->dumpOperand(m_specialPointer, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

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

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


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

    static OpJneqPtr decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

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

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

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpJneqPtr&) { }

        bool m_hasJumped;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_value;
    Special::Pointer m_specialPointer;
    BoundLabel m_targetLabel;
    unsigned m_metadataID;
};

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

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

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

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

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

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

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, 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(base)
            && Fits<VirtualRegister, size>::check(property)
            && 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, base, property, 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, size>::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<unsigned, size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_val_direct"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_value, false);
    }

    OpPutByValDirect(const uint8_t* stream)
        : m_base(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_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutByValDirect(const uint16_t* stream)
        : m_base(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_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutByValDirect(const uint32_t* stream)
        : m_base(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_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutByValDirect decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpPutByValDirect&) { }

        ArrayProfile m_arrayProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpPutByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_val;

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

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

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

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

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

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& property, 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(base)
            && Fits<VirtualRegister, size>::check(property)
            && 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, unsigned __metadataID)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, base, property, 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, size>::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<unsigned, size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_value, false);
    }

    OpPutByVal(const uint8_t* stream)
        : m_base(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_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutByVal(const uint16_t* stream)
        : m_base(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_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutByVal(const uint32_t* stream)
        : m_base(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_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutByVal decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpPutByVal&) { }

        ArrayProfile m_arrayProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

    OpGetByVal(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    OpGetByVal(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }


    OpGetByVal(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    static OpGetByVal decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetByVal&) { }

        ValueProfile m_profile;
        ArrayProfile m_arrayProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpPutById : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_id;

    static void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, value, flags);
    }

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

    template<OpcodeSize size>
    static bool checkWithoutMetadataID(BytecodeGenerator* gen, VirtualRegister base, unsigned property, VirtualRegister value, PutByIdFlags flags)
    {
        decltype(gen->addMetadataFor(opcodeID)) __metadataID { };
        return checkImpl<size>(gen, base, property, value, flags, __metadataID);
    }

    template<OpcodeSize size, 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>(gen, base, property, value, flags, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, value, flags, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, value, flags, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, value, flags, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_value, false);
        dumper->dumpOperand(m_flags, false);
    }

    OpPutById(const uint8_t* stream)
        : m_base(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_flags(Fits<PutByIdFlags, OpcodeSize::Narrow>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutById(const uint16_t* stream)
        : m_base(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_flags(Fits<PutByIdFlags, OpcodeSize::Wide16>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutById(const uint32_t* stream)
        : m_base(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_flags(Fits<PutByIdFlags, OpcodeSize::Wide32>::convert(stream[4]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFlags(PutByIdFlags value, Functor func)
    {
        if (isWide32())
            setFlags<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<PutByIdFlags, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        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);
    }

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_base;
    unsigned m_property;
    VirtualRegister m_value;
    PutByIdFlags m_flags;
    unsigned m_metadataID;
};

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**try_get_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

    OpTryGetById(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    OpTryGetById(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }


    OpTryGetById(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    static OpTryGetById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpTryGetById&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_id_direct"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

    OpGetByIdDirect(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    OpGetByIdDirect(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }


    OpGetByIdDirect(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    static OpGetByIdDirect decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetByIdDirect&) { }

        ValueProfile m_profile;
        StructureID m_structureID;
        unsigned m_offset;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpGetByValWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_val_with_this;

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

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

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

    template<OpcodeSize size, 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>(gen, dst, base, thisValue, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, thisValue, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_val_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_property, false);
    }

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

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


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

    static OpGetByValWithThis decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetByValWithThis&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

    template<OpcodeSize size, 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>(gen, dst, base, thisValue, property, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, thisValue, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, thisValue, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_id_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_property, false);
    }

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

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


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

    static OpGetByIdWithThis decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetByIdWithThis&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpGetById : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_by_id;

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

    OpGetById(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    OpGetById(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }


    OpGetById(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    static OpGetById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpGetById&) { }

        GetByIdModeMetadata m_modeMetadata;
        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

    template<OpcodeSize size, 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>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**add"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_operandTypes, false);
    }

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

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


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

    static OpAdd decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpAdd& __op)
            : m_arithProfile(__op.m_operandTypes)
        { }

        ArithProfile m_arithProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

    template<OpcodeSize size, 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>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mul"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_operandTypes, false);
    }

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

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


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

    static OpMul decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpMul& __op)
            : m_arithProfile(__op.m_operandTypes)
        { }

        ArithProfile m_arithProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs, OperandTypes operandTypes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs, operandTypes);
    }

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

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

    template<OpcodeSize size, 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>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**div"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_operandTypes, false);
    }

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

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


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

    static OpDiv decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpDiv& __op)
            : m_arithProfile(__op.m_operandTypes)
        { }

        ArithProfile m_arithProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpSub : public Instruction {
    static constexpr OpcodeID opcodeID = op_sub;

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

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

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

    template<OpcodeSize size, 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>(gen, dst, lhs, rhs, operandTypes, __metadataID);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, operandTypes, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**sub"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_operandTypes, false);
    }

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

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


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

    static OpSub decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpSub& __op)
            : m_arithProfile(__op.m_operandTypes)
        { }

        ArithProfile m_arithProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitand"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpBitand decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpBitand&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpBitor decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpBitor&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitxor"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpBitxor decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpBitxor&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**lshift"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpLshift decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpLshift&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

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

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**bitnot"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

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

    OpBitnot(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpBitnot(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpBitnot decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpBitnot&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_metadataID;
};

struct OpInByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_in_by_val;

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**in_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

    OpInByVal(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    OpInByVal(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }


    OpInByVal(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(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, stream[0] == opcodeID);
    }

    static OpInByVal decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpInByVal&) { }

        ArrayProfile m_arrayProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

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

struct OpNegate : public Instruction {
    static constexpr OpcodeID opcodeID = op_negate;

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

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

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

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

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

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& dst, VirtualRegister& operand, 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(operand)
            && 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, OperandTypes operandTypes, unsigned __metadataID)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, dst, operand, 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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            gen->write(Fits<OperandTypes, size>::convert(operandTypes));
            gen->write(Fits<unsigned, size>::convert(__metadataID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**negate"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
        dumper->dumpOperand(m_operandTypes, false);
    }

    OpNegate(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(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, stream[0] == opcodeID);
    }

    OpNegate(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(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, stream[0] == opcodeID);
    }


    OpNegate(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(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, stream[0] == opcodeID);
    }

    static OpNegate decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setOperandTypes(OperandTypes value, Functor func)
    {
        if (isWide32())
            setOperandTypes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<OperandTypes, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpNegate& __op)
            : m_arithProfile(__op.m_operandTypes)
        { }

        ArithProfile m_arithProfile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    OperandTypes m_operandTypes;
    unsigned m_metadataID;
};

struct OpToNumber : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_number;

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_number"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

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

    OpToNumber(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpToNumber(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpToNumber decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpToNumber&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_metadataID;
};

struct OpToObject : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_object;

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

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, operand, message, __metadataID))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, message, __metadataID))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, message, __metadataID);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
        dumper->dumpOperand(m_message, false);
    }

    OpToObject(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_message(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpToObject(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_message(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpToObject(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_message(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_metadataID(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpToObject decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setMessage(unsigned value, Functor func)
    {
        if (isWide32())
            setMessage<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    struct Metadata {
        WTF_MAKE_NONCOPYABLE(Metadata);

    public:
        Metadata(const OpToObject&) { }

        ValueProfile m_profile;
    };

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

    Metadata& metadata(ExecState* exec) const
    {
        return metadata(exec->codeBlock());
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    unsigned m_message;
    unsigned m_metadataID;
};

struct OpWide16 : public Instruction {
    static constexpr OpcodeID opcodeID = op_wide16;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**wide16"[2 - __sizeShiftAmount]);

    }

    OpWide16(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpWide16(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpWide16(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpWide16 decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpIsUndefined : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_undefined;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_undefined"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsUndefined(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsUndefined(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsUndefined(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsUndefined decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand);
    }

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_undefined_or_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsUndefinedOrNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsUndefinedOrNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsUndefinedOrNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsUndefinedOrNull decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpIsBoolean : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_boolean;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_boolean"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsBoolean(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsBoolean(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsBoolean(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsBoolean decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpIsNumber : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_number;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_number"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsNumber(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsNumber(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsNumber(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsNumber decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpIsObject : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_object;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_object"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsObject(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsObject(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsObject(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsObject decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpIsObjectOrNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_object_or_null;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_object_or_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsObjectOrNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsObjectOrNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsObjectOrNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsObjectOrNull decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpIsFunction : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_function;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_function"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsFunction(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsFunction(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsFunction(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsFunction decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpInc : public Instruction {
    static constexpr OpcodeID opcodeID = op_inc;

    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst);
    }

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: 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)
            && (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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, srcDst)) {
            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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(srcDst));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**inc"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_srcDst, true);
    }

    OpInc(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpInc(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpInc(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpInc decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_srcDst;
};

struct OpDec : public Instruction {
    static constexpr OpcodeID opcodeID = op_dec;

    static void emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, srcDst))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst);
    }

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& srcDst)
    {
        UNUSED_PARAM(gen);
#if OS(WINDOWS) && ENABLE(C_LOOP)
        // FIXME: 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)
            && (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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister srcDst)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, srcDst)) {
            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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(srcDst));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**dec"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_srcDst, true);
    }

    OpDec(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpDec(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpDec(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpDec decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_srcDst;
};

struct OpUnsigned : public Instruction {
    static constexpr OpcodeID opcodeID = op_unsigned;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**unsigned"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpUnsigned(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpUnsigned(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpUnsigned(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpUnsigned decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpToString : public Instruction {
    static constexpr OpcodeID opcodeID = op_to_string;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_string"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpToString(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpToString(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpToString(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpToString decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpNeqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_neq_null;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**neq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpNeqNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNeqNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNeqNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNeqNull decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpNot : public Instruction {
    static constexpr OpcodeID opcodeID = op_not;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**not"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpNot(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNot(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNot(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNot decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, srcDst, topProfile, bottomProfile);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister srcDst, unsigned topProfile, unsigned bottomProfile)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, srcDst, topProfile, bottomProfile);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, srcDst, topProfile, bottomProfile))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, srcDst, topProfile, bottomProfile))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, srcDst, topProfile, bottomProfile);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**identity_with_profile"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_srcDst, true);
        dumper->dumpOperand(m_topProfile, false);
        dumper->dumpOperand(m_bottomProfile, false);
    }

    OpIdentityWithProfile(const uint8_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_topProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_bottomProfile(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIdentityWithProfile(const uint16_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_topProfile(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIdentityWithProfile(const uint32_t* stream)
        : m_srcDst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_topProfile(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_bottomProfile(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIdentityWithProfile decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setSrcDst(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrcDst<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTopProfile(unsigned value, Functor func)
    {
        if (isWide32())
            setTopProfile<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setBottomProfile(unsigned value, Functor func)
    {
        if (isWide32())
            setBottomProfile<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, constructor, hasInstanceValue);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, dst, constructor, hasInstanceValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, constructor, hasInstanceValue))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, constructor, hasInstanceValue))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, constructor, hasInstanceValue);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**overrides_has_instance"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_constructor, false);
        dumper->dumpOperand(m_hasInstanceValue, false);
    }

    OpOverridesHasInstance(const uint8_t* stream)
        : m_dst(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, stream[0] == opcodeID);
    }

    OpOverridesHasInstance(const uint16_t* stream)
        : m_dst(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, stream[0] == opcodeID);
    }


    OpOverridesHasInstance(const uint32_t* stream)
        : m_dst(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, stream[0] == opcodeID);
    }

    static OpOverridesHasInstance decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setConstructor(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setConstructor<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setHasInstanceValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setHasInstanceValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister prototype)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, value, prototype);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, value, prototype))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, value, prototype))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, value, prototype);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**instanceof"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_value, false);
        dumper->dumpOperand(m_prototype, false);
    }

    OpInstanceof(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_prototype(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpInstanceof(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpInstanceof(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_prototype(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpInstanceof decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setPrototype(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setPrototype<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value, VirtualRegister constructor, VirtualRegister hasInstanceValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, value, constructor, hasInstanceValue);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, value, constructor, hasInstanceValue))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, value, constructor, hasInstanceValue);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**instanceof_custom"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_value, false);
        dumper->dumpOperand(m_constructor, false);
        dumper->dumpOperand(m_hasInstanceValue, false);
    }

    OpInstanceofCustom(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpInstanceofCustom(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpInstanceofCustom(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_constructor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_hasInstanceValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpInstanceofCustom decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setConstructor(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setConstructor<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setHasInstanceValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setHasInstanceValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, value);
    }

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

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

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**typeof"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_value, false);
    }

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

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


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

    static OpTypeof decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, operand, type);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand, JSType type)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, dst, operand, type);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, operand, type))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand, type))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand, type);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_cell_with_type"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
        dumper->dumpOperand(m_type, false);
    }

    OpIsCellWithType(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_type(Fits<JSType, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsCellWithType(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_type(Fits<JSType, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsCellWithType(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_type(Fits<JSType, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsCellWithType decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setType(JSType value, Functor func)
    {
        if (isWide32())
            setType<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<JSType, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
    JSType m_type;
};

struct OpEqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_eq_null;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**eq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpEqNull(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpEqNull(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpEqNull(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpEqNull decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpInById : public Instruction {
    static constexpr OpcodeID opcodeID = op_in_by_id;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**in_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

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

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


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

    static OpInById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
};

struct OpUrshift : public Instruction {
    static constexpr OpcodeID opcodeID = op_urshift;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**urshift"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpUrshift decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

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

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**rshift"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpRshift decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**pow"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpPow decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mod"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpMod decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**beloweq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpBeloweq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**below"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpBelow decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

struct OpPutByIdWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_id_with_this;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, thisValue, property, value))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, thisValue, property, value))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, thisValue, property, value);
    }

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& thisValue, unsigned& property, 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<VirtualRegister, size>::check(thisValue)
            && Fits<unsigned, size>::check(property)
            && 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, unsigned property, VirtualRegister value)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, base, thisValue, property, 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, size>::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));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_id_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_value, false);
    }

    OpPutByIdWithThis(const uint8_t* stream)
        : 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_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutByIdWithThis(const uint16_t* stream)
        : 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_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutByIdWithThis(const uint32_t* stream)
        : 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_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutByIdWithThis decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_thisValue;
    unsigned m_property;
    VirtualRegister m_value;
};

struct OpDelById : public Instruction {
    static constexpr OpcodeID opcodeID = op_del_by_id;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**del_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

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

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


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

    static OpDelById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    unsigned m_property;
};

struct OpGreatereq : public Instruction {
    static constexpr OpcodeID opcodeID = op_greatereq;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**greatereq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpGreatereq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**greater"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpGreater decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

struct OpPutByValWithThis : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_by_val_with_this;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, base, thisValue, property, value))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, thisValue, property, value))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, thisValue, property, value);
    }

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& base, VirtualRegister& thisValue, VirtualRegister& property, 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<VirtualRegister, size>::check(thisValue)
            && Fits<VirtualRegister, size>::check(property)
            && 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister thisValue, VirtualRegister property, VirtualRegister value)
    {
        if (size == OpcodeSize::Wide16)
            gen->alignWideOpcode16();
        else if (size == OpcodeSize::Wide32)
            gen->alignWideOpcode32();
        if (checkImpl<size>(gen, base, thisValue, property, 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, size>::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));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_by_val_with_this"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_thisValue, false);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_value, false);
    }

    OpPutByValWithThis(const uint8_t* stream)
        : 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_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutByValWithThis(const uint16_t* stream)
        : 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_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutByValWithThis(const uint32_t* stream)
        : 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_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutByValWithThis decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_thisValue;
    VirtualRegister m_property;
    VirtualRegister m_value;
};

struct OpLesseq : public Instruction {
    static constexpr OpcodeID opcodeID = op_lesseq;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**lesseq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpLesseq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

struct OpDelByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_del_by_val;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**del_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

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

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


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

    static OpDelByVal decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
};

struct OpPutGetterById : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_getter_by_id;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_getter_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_attributes, false);
        dumper->dumpOperand(m_accessor, false);
    }

    OpPutGetterById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutGetterById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutGetterById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutGetterById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister accessor)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, accessor);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_setter_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_attributes, false);
        dumper->dumpOperand(m_accessor, false);
    }

    OpPutSetterById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutSetterById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutSetterById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutSetterById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister base, unsigned property, unsigned attributes, VirtualRegister getter, VirtualRegister setter)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, getter, setter);
    }

    template<OpcodeSize size, 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>(gen, base, property, attributes, getter, setter);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, attributes, getter, setter))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, getter, setter))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, getter, setter);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_getter_setter_by_id"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_attributes, false);
        dumper->dumpOperand(m_getter, false);
        dumper->dumpOperand(m_setter, false);
    }

    OpPutGetterSetterById(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutGetterSetterById(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutGetterSetterById(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutGetterSetterById decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setGetter(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setGetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSetter(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, unsigned attributes, VirtualRegister accessor)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, attributes, accessor);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_getter_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_attributes, false);
        dumper->dumpOperand(m_accessor, false);
    }

    OpPutGetterByVal(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutGetterByVal(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutGetterByVal(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutGetterByVal decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_base;
    VirtualRegister m_property;
    unsigned m_attributes;
    VirtualRegister m_accessor;
};

struct OpPutSetterByVal : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_setter_by_val;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, attributes, accessor))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, attributes, accessor);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_setter_by_val"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_attributes, false);
        dumper->dumpOperand(m_accessor, false);
    }

    OpPutSetterByVal(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutSetterByVal(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutSetterByVal(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_attributes(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
        , m_accessor(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutSetterByVal decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(unsigned value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setAccessor(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setAccessor<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, value, attributes);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister value, VirtualRegister attributes)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, base, property, value, attributes);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, value, attributes))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, value, attributes))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, value, attributes);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**define_data_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_value, false);
        dumper->dumpOperand(m_attributes, false);
    }

    OpDefineDataProperty(const uint8_t* stream)
        : m_base(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_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpDefineDataProperty(const uint16_t* stream)
        : m_base(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_attributes(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpDefineDataProperty(const uint32_t* stream)
        : m_base(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_attributes(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpDefineDataProperty decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister base, VirtualRegister property, VirtualRegister getter, VirtualRegister setter, VirtualRegister attributes)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, base, property, getter, setter, attributes);
    }

    template<OpcodeSize size, 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>(gen, base, property, getter, setter, attributes);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, base, property, getter, setter, attributes))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, base, property, getter, setter, attributes))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, base, property, getter, setter, attributes);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**define_accessor_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_base, true);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_getter, false);
        dumper->dumpOperand(m_setter, false);
        dumper->dumpOperand(m_attributes, false);
    }

    OpDefineAccessorProperty(const uint8_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpDefineAccessorProperty(const uint16_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpDefineAccessorProperty(const uint32_t* stream)
        : m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_getter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_setter(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
        , m_attributes(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[5]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpDefineAccessorProperty decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setGetter(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setGetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSetter(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSetter<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setAttributes(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setAttributes<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 5 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<BoundLabel, size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jmp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_targetLabel, true);
    }

    OpJmp(const uint8_t* stream)
        : m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJmp(const uint16_t* stream)
        : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJmp(const uint32_t* stream)
        : m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJmp decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    BoundLabel m_targetLabel;
};

struct OpJtrue : public Instruction {
    static constexpr OpcodeID opcodeID = op_jtrue;

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

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, condition, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, condition, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(condition));
            gen->write(Fits<BoundLabel, size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jtrue"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_condition, true);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJtrue(const uint8_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJtrue(const uint16_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJtrue(const uint32_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJtrue decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_condition;
    BoundLabel m_targetLabel;
};

struct OpJfalse : public Instruction {
    static constexpr OpcodeID opcodeID = op_jfalse;

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

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, condition, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister condition, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, condition, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, condition, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(condition));
            gen->write(Fits<BoundLabel, size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jfalse"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_condition, true);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJfalse(const uint8_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJfalse(const uint16_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJfalse(const uint32_t* stream)
        : m_condition(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJfalse decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setCondition(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCondition<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_condition;
    BoundLabel m_targetLabel;
};

struct OpJeqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_jeq_null;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, value, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            gen->write(Fits<BoundLabel, size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jeq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_value, true);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJeqNull(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJeqNull(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJeqNull(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJeqNull decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_value;
    BoundLabel m_targetLabel;
};

struct OpJneqNull : public Instruction {
    static constexpr OpcodeID opcodeID = op_jneq_null;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value, BoundLabel targetLabel)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, value, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            gen->write(Fits<BoundLabel, size>::convert(targetLabel));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jneq_null"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_value, true);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJneqNull(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJneqNull(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJneqNull(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJneqNull decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    VirtualRegister m_value;
    BoundLabel m_targetLabel;
};

struct OpLess : public Instruction {
    static constexpr OpcodeID opcodeID = op_less;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**less"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpLess decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

struct OpJeq : public Instruction {
    static constexpr OpcodeID opcodeID = op_jeq;

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

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jeq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJeq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJeq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJeq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJeq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jstricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJstricteq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJstricteq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJstricteq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJstricteq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jneq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJneq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJneq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJneq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJneq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnstricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJnstricteq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJnstricteq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJnstricteq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJnstricteq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jless"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJless(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJless(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJless(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJless decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jlesseq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJlesseq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJlesseq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJlesseq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJlesseq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jgreater"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJgreater(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJgreater(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJgreater(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJgreater decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jgreatereq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJgreatereq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJgreatereq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJgreatereq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJgreatereq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnless"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJnless(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJnless(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJnless(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJnless decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jnlesseq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJnlesseq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJnlesseq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJnlesseq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJnlesseq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jngreater"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJngreater(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJngreater(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJngreater(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJngreater decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jngreatereq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJngreatereq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJngreatereq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJngreatereq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJngreatereq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jbelow"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJbelow(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJbelow(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJbelow(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJbelow decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, lhs, rhs, targetLabel);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister lhs, VirtualRegister rhs, BoundLabel targetLabel)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, lhs, rhs, targetLabel);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, lhs, rhs, targetLabel))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, lhs, rhs, targetLabel);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**jbeloweq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_lhs, true);
        dumper->dumpOperand(m_rhs, false);
        dumper->dumpOperand(m_targetLabel, false);
    }

    OpJbeloweq(const uint8_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpJbeloweq(const uint16_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpJbeloweq(const uint32_t* stream)
        : m_lhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_rhs(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_targetLabel(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpJbeloweq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setTargetLabel(BoundLabel value, Functor func)
    {
        if (isWide32())
            setTargetLabel<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**loop_hint"[2 - __sizeShiftAmount]);

    }

    OpLoopHint(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpLoopHint(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpLoopHint(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpLoopHint decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpSwitchImm : public Instruction {
    static constexpr OpcodeID opcodeID = op_switch_imm;

    static void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, tableIndex, defaultOffset, scrutinee);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch_imm"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_tableIndex, true);
        dumper->dumpOperand(m_defaultOffset, false);
        dumper->dumpOperand(m_scrutinee, false);
    }

    OpSwitchImm(const uint8_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSwitchImm(const uint16_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSwitchImm(const uint32_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSwitchImm decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (isWide32())
            setDefaultOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, tableIndex, defaultOffset, scrutinee);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch_char"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_tableIndex, true);
        dumper->dumpOperand(m_defaultOffset, false);
        dumper->dumpOperand(m_scrutinee, false);
    }

    OpSwitchChar(const uint8_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSwitchChar(const uint16_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSwitchChar(const uint32_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSwitchChar decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (isWide32())
            setDefaultOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, tableIndex, defaultOffset, scrutinee);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, unsigned tableIndex, BoundLabel defaultOffset, VirtualRegister scrutinee)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, tableIndex, defaultOffset, scrutinee);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, tableIndex, defaultOffset, scrutinee))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, tableIndex, defaultOffset, scrutinee);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**switch_string"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_tableIndex, true);
        dumper->dumpOperand(m_defaultOffset, false);
        dumper->dumpOperand(m_scrutinee, false);
    }

    OpSwitchString(const uint8_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Narrow>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSwitchString(const uint16_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide16>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSwitchString(const uint32_t* stream)
        : m_tableIndex(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[1]))
        , m_defaultOffset(Fits<BoundLabel, OpcodeSize::Wide32>::convert(stream[2]))
        , m_scrutinee(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSwitchString decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTableIndex(unsigned value, Functor func)
    {
        if (isWide32())
            setTableIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setDefaultOffset(BoundLabel value, Functor func)
    {
        if (isWide32())
            setDefaultOffset<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<BoundLabel, size>::convert(value);
    }

    template<typename Functor>
    void setScrutinee(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScrutinee<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewFunc decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewFuncExp decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_generator_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewGeneratorFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewGeneratorFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewGeneratorFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewGeneratorFunc decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_generator_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewGeneratorFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewGeneratorFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewGeneratorFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewGeneratorFuncExp decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewAsyncFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewAsyncFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewAsyncFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewAsyncFunc decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewAsyncFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewAsyncFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewAsyncFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewAsyncFuncExp decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_generator_func"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewAsyncGeneratorFunc(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewAsyncGeneratorFunc(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewAsyncGeneratorFunc(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewAsyncGeneratorFunc decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned functionDecl)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, functionDecl);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, functionDecl))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, functionDecl);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_async_generator_func_exp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_functionDecl, false);
    }

    OpNewAsyncGeneratorFuncExp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewAsyncGeneratorFuncExp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewAsyncGeneratorFuncExp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_functionDecl(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewAsyncGeneratorFuncExp decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setFunctionDecl(unsigned value, Functor func)
    {
        if (isWide32())
            setFunctionDecl<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, function, name);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, function, name);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister function, VirtualRegister name)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, function, name))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, function, name))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, function, name);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(function));
            gen->write(Fits<VirtualRegister, size>::convert(name));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**set_function_name"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_function, true);
        dumper->dumpOperand(m_name, false);
    }

    OpSetFunctionName(const uint8_t* stream)
        : m_function(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_name(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSetFunctionName(const uint16_t* stream)
        : m_function(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_name(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSetFunctionName(const uint32_t* stream)
        : m_function(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_name(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSetFunctionName decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setFunction(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setFunction<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setName(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setName<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_function;
    VirtualRegister m_name;
};

struct OpNstricteq : public Instruction {
    static constexpr OpcodeID opcodeID = op_nstricteq;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**nstricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpNstricteq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**stricteq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpStricteq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister lhs, VirtualRegister rhs)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, lhs, rhs);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**neq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpNeq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

struct OpEq : public Instruction {
    static constexpr OpcodeID opcodeID = op_eq;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, lhs, rhs))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, lhs, rhs);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**eq"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_lhs, false);
        dumper->dumpOperand(m_rhs, false);
    }

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

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


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

    static OpEq decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setLhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setLhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setRhs(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRhs<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_lhs;
    VirtualRegister m_rhs;
};

struct OpIsEmpty : public Instruction {
    static constexpr OpcodeID opcodeID = op_is_empty;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister operand)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, operand))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, operand))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, operand);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(operand));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**is_empty"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_operand, false);
    }

    OpIsEmpty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpIsEmpty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpIsEmpty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_operand(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpIsEmpty decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setOperand(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setOperand<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_operand;
};

struct OpMov : public Instruction {
    static constexpr OpcodeID opcodeID = op_mov;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, src))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, src);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(src));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**mov"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_src, false);
    }

    OpMov(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpMov(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpMov(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpMov decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
};

struct OpNewRegexp : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_regexp;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister regexp)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, regexp))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, regexp))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, regexp);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(regexp));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_regexp"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_regexp, false);
    }

    OpNewRegexp(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_regexp(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNewRegexp(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNewRegexp(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_regexp(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNewRegexp decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setRegexp(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setRegexp<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_regexp;
};

struct OpSpread : public Instruction {
    static constexpr OpcodeID opcodeID = op_spread;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister argument)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, argument))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, argument))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, argument);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(argument));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**spread"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_argument, false);
    }

    OpSpread(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSpread(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSpread(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSpread decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setArgument(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArgument<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_argument;
};

struct OpRet : public Instruction {
    static constexpr OpcodeID opcodeID = op_ret;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, value);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**ret"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_value, true);
    }

    OpRet(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpRet(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpRet(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpRet decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_value;
};

struct OpStrcat : public Instruction {
    static constexpr OpcodeID opcodeID = op_strcat;

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

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src, int count)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, dst, src, count);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, src, count))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, src, count))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, src, count);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**strcat"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_src, false);
        dumper->dumpOperand(m_count, false);
    }

    OpStrcat(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_count(Fits<int, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpStrcat(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_count(Fits<int, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpStrcat(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_count(Fits<int, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpStrcat decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setCount(int value, Functor func)
    {
        if (isWide32())
            setCount<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, src);
    }

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister src)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, src))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, src))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, src);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(src));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_primitive"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_src, false);
    }

    OpToPrimitive(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpToPrimitive(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpToPrimitive(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_src(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpToPrimitive decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setSrc(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSrc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_src;
};

struct OpNewArrayWithSpread : public Instruction {
    static constexpr OpcodeID opcodeID = op_new_array_with_spread;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, argv, argc, bitVector))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, argv, argc, bitVector))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, argv, argc, bitVector);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**new_array_with_spread"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_argv, false);
        dumper->dumpOperand(m_argc, false);
        dumper->dumpOperand(m_bitVector, false);
    }

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

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


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

    static OpNewArrayWithSpread decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setArgv(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArgv<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setArgc(unsigned value, Functor func)
    {
        if (isWide32())
            setArgc<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setBitVector(unsigned value, Functor func)
    {
        if (isWide32())
            setBitVector<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_argv;
    unsigned m_argc;
    unsigned m_bitVector;
};

struct OpCheckTdz : public Instruction {
    static constexpr OpcodeID opcodeID = op_check_tdz;

    static void emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, targetVirtualRegister);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, targetVirtualRegister);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister targetVirtualRegister)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, targetVirtualRegister))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, targetVirtualRegister))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, targetVirtualRegister);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(targetVirtualRegister));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**check_tdz"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_targetVirtualRegister, true);
    }

    OpCheckTdz(const uint8_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCheckTdz(const uint16_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCheckTdz(const uint32_t* stream)
        : m_targetVirtualRegister(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCheckTdz decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setTargetVirtualRegister(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setTargetVirtualRegister<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_targetVirtualRegister;
};

struct OpArgumentCount : public Instruction {
    static constexpr OpcodeID opcodeID = op_argument_count;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**argument_count"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
    }

    OpArgumentCount(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpArgumentCount(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpArgumentCount(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpArgumentCount decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    VirtualRegister m_dst;
};

struct OpCreateClonedArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_cloned_arguments;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_cloned_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
    }

    OpCreateClonedArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCreateClonedArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCreateClonedArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCreateClonedArguments decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    VirtualRegister m_dst;
};

struct OpPutToArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_put_to_arguments;

    static void emit(BytecodeGenerator* gen, VirtualRegister arguments, unsigned index, VirtualRegister value)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, arguments, index, value);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, arguments, index, value))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, arguments, index, value))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, arguments, index, value);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**put_to_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_arguments, true);
        dumper->dumpOperand(m_index, false);
        dumper->dumpOperand(m_value, false);
    }

    OpPutToArguments(const uint8_t* stream)
        : m_arguments(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPutToArguments(const uint16_t* stream)
        : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPutToArguments(const uint32_t* stream)
        : m_arguments(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_index(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPutToArguments decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setArguments(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArguments<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(unsigned value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, currentScope, newScope);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister currentScope, VirtualRegister newScope)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, dst, currentScope, newScope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, currentScope, newScope))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, currentScope, newScope))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, currentScope, newScope);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**push_with_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_currentScope, false);
        dumper->dumpOperand(m_newScope, false);
    }

    OpPushWithScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_currentScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_newScope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpPushWithScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpPushWithScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_currentScope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_newScope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpPushWithScope decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setCurrentScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setCurrentScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNewScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setNewScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, symbolTable, initialValue);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, symbolTable, initialValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, symbolTable, initialValue);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_lexical_environment"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_symbolTable, false);
        dumper->dumpOperand(m_initialValue, false);
    }

    OpCreateLexicalEnvironment(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCreateLexicalEnvironment(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCreateLexicalEnvironment(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCreateLexicalEnvironment decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTable(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSymbolTable<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInitialValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setInitialValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, symbolTable, initialValue);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, VirtualRegister symbolTable, VirtualRegister initialValue)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, dst, scope, symbolTable, initialValue);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, symbolTable, initialValue))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, symbolTable, initialValue);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_generator_frame_environment"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_symbolTable, false);
        dumper->dumpOperand(m_initialValue, false);
    }

    OpCreateGeneratorFrameEnvironment(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCreateGeneratorFrameEnvironment(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCreateGeneratorFrameEnvironment(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_symbolTable(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_initialValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCreateGeneratorFrameEnvironment decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setSymbolTable(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setSymbolTable<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setInitialValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setInitialValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 4 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope);
    }

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_parent_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
    }

    OpGetParentScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetParentScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetParentScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetParentScope decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
};

struct OpCreateScopedArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_scoped_arguments;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, scope))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_scoped_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
    }

    OpCreateScopedArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCreateScopedArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCreateScopedArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCreateScopedArguments decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
};

struct OpThrow : public Instruction {
    static constexpr OpcodeID opcodeID = op_throw;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, value);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**throw"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_value, true);
    }

    OpThrow(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpThrow(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpThrow(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpThrow decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_value;
};

struct OpThrowStaticError : public Instruction {
    static constexpr OpcodeID opcodeID = op_throw_static_error;

    static void emit(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, message, errorType);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, message, errorType);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister message, ErrorType errorType)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, message, errorType))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, message, errorType))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, message, errorType);
    }

private:
    template<OpcodeSize size>
    static bool checkImpl(BytecodeGenerator* gen, VirtualRegister& message, ErrorType& 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<ErrorType, 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>
    static bool emitImpl(BytecodeGenerator* gen, VirtualRegister message, ErrorType 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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(message));
            gen->write(Fits<ErrorType, size>::convert(errorType));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**throw_static_error"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_message, true);
        dumper->dumpOperand(m_errorType, false);
    }

    OpThrowStaticError(const uint8_t* stream)
        : m_message(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_errorType(Fits<ErrorType, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpThrowStaticError(const uint16_t* stream)
        : m_message(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_errorType(Fits<ErrorType, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpThrowStaticError(const uint32_t* stream)
        : m_message(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_errorType(Fits<ErrorType, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpThrowStaticError decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setMessage(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setMessage<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

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

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

    VirtualRegister m_message;
    ErrorType m_errorType;
};

struct OpDebug : public Instruction {
    static constexpr OpcodeID opcodeID = op_debug;

    static void emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, debugHookType, hasBreakpoint);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, debugHookType, hasBreakpoint);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, DebugHookType debugHookType, bool hasBreakpoint)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, debugHookType, hasBreakpoint))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, debugHookType, hasBreakpoint))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, debugHookType, hasBreakpoint);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<DebugHookType, size>::convert(debugHookType));
            gen->write(Fits<bool, size>::convert(hasBreakpoint));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**debug"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_debugHookType, true);
        dumper->dumpOperand(m_hasBreakpoint, false);
    }

    OpDebug(const uint8_t* stream)
        : m_debugHookType(Fits<DebugHookType, OpcodeSize::Narrow>::convert(stream[1]))
        , m_hasBreakpoint(Fits<bool, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpDebug(const uint16_t* stream)
        : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide16>::convert(stream[1]))
        , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpDebug(const uint32_t* stream)
        : m_debugHookType(Fits<DebugHookType, OpcodeSize::Wide32>::convert(stream[1]))
        , m_hasBreakpoint(Fits<bool, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpDebug decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setDebugHookType(DebugHookType value, Functor func)
    {
        if (isWide32())
            setDebugHookType<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<DebugHookType, size>::convert(value);
    }

    template<typename Functor>
    void setHasBreakpoint(bool value, Functor func)
    {
        if (isWide32())
            setHasBreakpoint<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<bool, size>::convert(value);
    }

    DebugHookType m_debugHookType;
    bool m_hasBreakpoint;
};

struct OpEnd : public Instruction {
    static constexpr OpcodeID opcodeID = op_end;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister value)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, value))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, value))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, value);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(value));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**end"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_value, true);
    }

    OpEnd(const uint8_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpEnd(const uint16_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpEnd(const uint32_t* stream)
        : m_value(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpEnd decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_value;
};

struct OpCreateDirectArguments : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_direct_arguments;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_direct_arguments"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
    }

    OpCreateDirectArguments(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCreateDirectArguments(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCreateDirectArguments(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCreateDirectArguments decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    VirtualRegister m_dst;
};

struct OpGetScope : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_scope;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_scope"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
    }

    OpGetScope(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetScope(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetScope(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetScope decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    VirtualRegister m_dst;
};

struct OpGetEnumerableLength : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_enumerable_length;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(base));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_enumerable_length"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
    }

    OpGetEnumerableLength(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetEnumerableLength(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetEnumerableLength(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetEnumerableLength decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
};

struct OpEnter : public Instruction {
    static constexpr OpcodeID opcodeID = op_enter;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enter"[2 - __sizeShiftAmount]);

    }

    OpEnter(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpEnter(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpEnter(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpEnter decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpHasStructureProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_structure_property;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property, enumerator))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property, enumerator);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_structure_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
        dumper->dumpOperand(m_enumerator, false);
    }

    OpHasStructureProperty(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpHasStructureProperty(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpHasStructureProperty(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_property(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[4]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpHasStructureProperty decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
    VirtualRegister m_enumerator;
};

struct OpHasGenericProperty : public Instruction {
    static constexpr OpcodeID opcodeID = op_has_generic_property;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, base, property))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base, property))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base, property);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**has_generic_property"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
        dumper->dumpOperand(m_property, false);
    }

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

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


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

    static OpHasGenericProperty decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_base;
    VirtualRegister m_property;
};

struct OpWide32 : public Instruction {
    static constexpr OpcodeID opcodeID = op_wide32;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**wide32"[2 - __sizeShiftAmount]);

    }

    OpWide32(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpWide32(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpWide32(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpWide32 decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpGetPropertyEnumerator : public Instruction {
    static constexpr OpcodeID opcodeID = op_get_property_enumerator;

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

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister base)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, base))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, base))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, base);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(base));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_property_enumerator"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_base, false);
    }

    OpGetPropertyEnumerator(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpGetPropertyEnumerator(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetPropertyEnumerator(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_base(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetPropertyEnumerator decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setBase(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setBase<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, enumerator, index);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, enumerator, index);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enumerator_structure_pname"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_enumerator, false);
        dumper->dumpOperand(m_index, false);
    }

    OpEnumeratorStructurePname(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpEnumeratorStructurePname(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpEnumeratorStructurePname(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpEnumeratorStructurePname decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister enumerator, VirtualRegister index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, enumerator, index);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, enumerator, index))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, enumerator, index);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**enumerator_generic_pname"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_enumerator, false);
        dumper->dumpOperand(m_index, false);
    }

    OpEnumeratorGenericPname(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpEnumeratorGenericPname(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpEnumeratorGenericPname(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_enumerator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpEnumeratorGenericPname decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setEnumerator(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setEnumerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, index);
    }

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister index)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, index))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, index))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, index);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<VirtualRegister, size>::convert(index));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**to_index_string"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_index, false);
    }

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

    OpToIndexString(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpToIndexString(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_index(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpToIndexString decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setIndex(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setIndex<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_index;
};

struct OpUnreachable : public Instruction {
    static constexpr OpcodeID opcodeID = op_unreachable;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**unreachable"[2 - __sizeShiftAmount]);

    }

    OpUnreachable(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpUnreachable(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpUnreachable(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpUnreachable decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpCreateRest : public Instruction {
    static constexpr OpcodeID opcodeID = op_create_rest;

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

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, arraySize, numParametersToSkip))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, arraySize, numParametersToSkip))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, arraySize, numParametersToSkip);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**create_rest"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_arraySize, false);
        dumper->dumpOperand(m_numParametersToSkip, false);
    }

    OpCreateRest(const uint8_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_arraySize(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCreateRest(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCreateRest(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_arraySize(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCreateRest decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setArraySize(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArraySize<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setNumParametersToSkip(unsigned value, Functor func)
    {
        if (isWide32())
            setNumParametersToSkip<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, numParametersToSkip);
    }

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

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister dst, unsigned numParametersToSkip)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, dst, numParametersToSkip))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, numParametersToSkip))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, numParametersToSkip);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(dst));
            gen->write(Fits<unsigned, size>::convert(numParametersToSkip));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**get_rest_length"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_numParametersToSkip, false);
    }

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

    OpGetRestLength(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpGetRestLength(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_numParametersToSkip(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpGetRestLength decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setNumParametersToSkip(unsigned value, Functor func)
    {
        if (isWide32())
            setNumParametersToSkip<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    unsigned m_numParametersToSkip;
};

struct OpYield : public Instruction {
    static constexpr OpcodeID opcodeID = op_yield;

    static void emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, generator, yieldPoint, argument);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister generator, unsigned yieldPoint, VirtualRegister argument)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, generator, yieldPoint, argument);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    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, NoAssert, true>(gen, generator, yieldPoint, argument))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, generator, yieldPoint, argument))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, generator, yieldPoint, argument);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**yield"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_generator, true);
        dumper->dumpOperand(m_yieldPoint, false);
        dumper->dumpOperand(m_argument, false);
    }

    OpYield(const uint8_t* stream)
        : m_generator(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_yieldPoint(Fits<unsigned, OpcodeSize::Narrow>::convert(stream[2]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpYield(const uint16_t* stream)
        : m_generator(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[2]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpYield(const uint32_t* stream)
        : m_generator(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_yieldPoint(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[2]))
        , m_argument(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpYield decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setGenerator(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setGenerator<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 1 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setYieldPoint(unsigned value, Functor func)
    {
        if (isWide32())
            setYieldPoint<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<unsigned, size>::convert(value);
    }

    template<typename Functor>
    void setArgument(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setArgument<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 3 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**check_traps"[2 - __sizeShiftAmount]);

    }

    OpCheckTraps(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpCheckTraps(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpCheckTraps(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpCheckTraps decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpLogShadowChickenPrologue : public Instruction {
    static constexpr OpcodeID opcodeID = op_log_shadow_chicken_prologue;

    static void emit(BytecodeGenerator* gen, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, scope);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister scope)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, scope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, scope))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, scope))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, scope);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**log_shadow_chicken_prologue"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_scope, true);
    }

    OpLogShadowChickenPrologue(const uint8_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpLogShadowChickenPrologue(const uint16_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpLogShadowChickenPrologue(const uint32_t* stream)
        : m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpLogShadowChickenPrologue decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    VirtualRegister m_scope;
};

struct OpLogShadowChickenTail : public Instruction {
    static constexpr OpcodeID opcodeID = op_log_shadow_chicken_tail;

    static void emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, thisValue, scope);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen, thisValue, scope);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen, VirtualRegister thisValue, VirtualRegister scope)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen, thisValue, scope))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, thisValue, scope))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, thisValue, scope);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            gen->write(Fits<VirtualRegister, size>::convert(thisValue));
            gen->write(Fits<VirtualRegister, size>::convert(scope));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**log_shadow_chicken_tail"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_thisValue, true);
        dumper->dumpOperand(m_scope, false);
    }

    OpLogShadowChickenTail(const uint8_t* stream)
        : m_thisValue(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Narrow>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpLogShadowChickenTail(const uint16_t* stream)
        : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpLogShadowChickenTail(const uint32_t* stream)
        : m_thisValue(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpLogShadowChickenTail decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

    template<typename Functor>
    void setThisValue(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setThisValue<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *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 void emit(BytecodeGenerator* gen, VirtualRegister dst, VirtualRegister scope, unsigned property)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen, dst, scope, property);
    }

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

    template<OpcodeSize size>
    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, NoAssert, true>(gen, dst, scope, property))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen, dst, scope, property))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen, dst, scope, property);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::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:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**resolve_scope_for_hoisting_func_decl_in_eval"[2 - __sizeShiftAmount]);
        dumper->dumpOperand(m_dst, true);
        dumper->dumpOperand(m_scope, false);
        dumper->dumpOperand(m_property, false);
    }

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

    OpResolveScopeForHoistingFuncDeclInEval(const uint16_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide16>::convert(stream[2]))
        , m_property(Fits<unsigned, OpcodeSize::Wide16>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpResolveScopeForHoistingFuncDeclInEval(const uint32_t* stream)
        : m_dst(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[1]))
        , m_scope(Fits<VirtualRegister, OpcodeSize::Wide32>::convert(stream[2]))
        , m_property(Fits<unsigned, OpcodeSize::Wide32>::convert(stream[3]))
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpResolveScopeForHoistingFuncDeclInEval decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }

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

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

    template<typename Functor>
    void setScope(VirtualRegister value, Functor func)
    {
        if (isWide32())
            setScope<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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) + 2 * size + PaddingBySize<size>::value);
        *stream = Fits<VirtualRegister, size>::convert(value);
    }

    template<typename Functor>
    void setProperty(unsigned value, Functor func)
    {
        if (isWide32())
            setProperty<OpcodeSize::Wide32>(value, func);
        else if (isWide16())
            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);
        *stream = Fits<unsigned, size>::convert(value);
    }

    VirtualRegister m_dst;
    VirtualRegister m_scope;
    unsigned m_property;
};

struct OpNop : public Instruction {
    static constexpr OpcodeID opcodeID = op_nop;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**nop"[2 - __sizeShiftAmount]);

    }

    OpNop(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpNop(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpNop(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpNop decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpSuperSamplerBegin : public Instruction {
    static constexpr OpcodeID opcodeID = op_super_sampler_begin;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**super_sampler_begin"[2 - __sizeShiftAmount]);

    }

    OpSuperSamplerBegin(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSuperSamplerBegin(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSuperSamplerBegin(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSuperSamplerBegin decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

struct OpSuperSamplerEnd : public Instruction {
    static constexpr OpcodeID opcodeID = op_super_sampler_end;

    static void emit(BytecodeGenerator* gen)
    {
        emitWithSmallestSizeRequirement<OpcodeSize::Narrow>(gen);
    }

    template<OpcodeSize size, FitsAssertion shouldAssert = Assert, bool recordOpcode = true>
    static bool emit(BytecodeGenerator* gen)
    {
        bool didEmit = emitImpl<size, recordOpcode>(gen);
        if (shouldAssert == Assert)
            ASSERT(didEmit);
        return didEmit;
    }

    template<OpcodeSize size>
    static void emitWithSmallestSizeRequirement(BytecodeGenerator* gen)
    {
        
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Narrow)) {
            if (emit<OpcodeSize::Narrow, NoAssert, true>(gen))
                return;
        }
        if (static_cast<unsigned>(size) <= static_cast<unsigned>(OpcodeSize::Wide16)) {
            if (emit<OpcodeSize::Wide16, NoAssert, true>(gen))
                return;
        }
        emit<OpcodeSize::Wide32, Assert, true>(gen);
    }

private:
    template<OpcodeSize size>
    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>
    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, size>::convert(opcodeID));
            return true;
        }
        return false;
    }

public:
    template<typename Block>
    void dump(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, int __sizeShiftAmount)
    {
        dumper->printLocationAndOp(__location, &"**super_sampler_end"[2 - __sizeShiftAmount]);

    }

    OpSuperSamplerEnd(const uint8_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    OpSuperSamplerEnd(const uint16_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }


    OpSuperSamplerEnd(const uint32_t* stream)
        
    {
        ASSERT_UNUSED(stream, stream[0] == opcodeID);
    }

    static OpSuperSamplerEnd decode(const uint8_t* stream)
    {
        if (*stream == op_wide32) 
            return { bitwise_cast<const uint32_t*>(stream + 1) };
        if (*stream == op_wide16) 
            return { bitwise_cast<const uint16_t*>(stream + 1) };
        return { stream };
    }



};

template<typename Block>
static void dumpBytecode(BytecodeDumper<Block>* dumper, InstructionStream::Offset __location, const Instruction* __instruction)
{
    switch (__instruction->opcodeID()) {
    case op_tail_call_varargs:
        __instruction->as<OpTailCallVarargs>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_direct_pname:
        __instruction->as<OpGetDirectPname>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_has_indexed_property:
        __instruction->as<OpHasIndexedProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_profile_control_flow:
        __instruction->as<OpProfileControlFlow>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_profile_type:
        __instruction->as<OpProfileType>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_catch:
        __instruction->as<OpCatch>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_from_arguments:
        __instruction->as<OpGetFromArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_this:
        __instruction->as<OpCreateThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_argument:
        __instruction->as<OpGetArgument>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_to_scope:
        __instruction->as<OpPutToScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_to_this:
        __instruction->as<OpToThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_from_scope:
        __instruction->as<OpGetFromScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_object:
        __instruction->as<OpNewObject>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_array:
        __instruction->as<OpNewArray>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_array_with_size:
        __instruction->as<OpNewArrayWithSize>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_array_buffer:
        __instruction->as<OpNewArrayBuffer>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_resolve_scope:
        __instruction->as<OpResolveScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_construct_varargs:
        __instruction->as<OpConstructVarargs>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_construct:
        __instruction->as<OpConstruct>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_tail_call_forward_arguments:
        __instruction->as<OpTailCallForwardArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_call_varargs:
        __instruction->as<OpCallVarargs>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_call_eval:
        __instruction->as<OpCallEval>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_tail_call:
        __instruction->as<OpTailCall>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_call:
        __instruction->as<OpCall>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jneq_ptr:
        __instruction->as<OpJneqPtr>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_by_val_direct:
        __instruction->as<OpPutByValDirect>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_by_val:
        __instruction->as<OpPutByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_by_val:
        __instruction->as<OpGetByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_by_id:
        __instruction->as<OpPutById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_try_get_by_id:
        __instruction->as<OpTryGetById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_by_id_direct:
        __instruction->as<OpGetByIdDirect>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_by_val_with_this:
        __instruction->as<OpGetByValWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_by_id_with_this:
        __instruction->as<OpGetByIdWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_by_id:
        __instruction->as<OpGetById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_add:
        __instruction->as<OpAdd>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_mul:
        __instruction->as<OpMul>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_div:
        __instruction->as<OpDiv>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_sub:
        __instruction->as<OpSub>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_bitand:
        __instruction->as<OpBitand>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_bitor:
        __instruction->as<OpBitor>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_bitxor:
        __instruction->as<OpBitxor>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_lshift:
        __instruction->as<OpLshift>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_bitnot:
        __instruction->as<OpBitnot>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_in_by_val:
        __instruction->as<OpInByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_negate:
        __instruction->as<OpNegate>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_to_number:
        __instruction->as<OpToNumber>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_to_object:
        __instruction->as<OpToObject>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_wide16:
        __instruction->as<OpWide16>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_undefined:
        __instruction->as<OpIsUndefined>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_undefined_or_null:
        __instruction->as<OpIsUndefinedOrNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_boolean:
        __instruction->as<OpIsBoolean>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_number:
        __instruction->as<OpIsNumber>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_object:
        __instruction->as<OpIsObject>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_object_or_null:
        __instruction->as<OpIsObjectOrNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_function:
        __instruction->as<OpIsFunction>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_inc:
        __instruction->as<OpInc>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_dec:
        __instruction->as<OpDec>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_unsigned:
        __instruction->as<OpUnsigned>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_to_string:
        __instruction->as<OpToString>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_neq_null:
        __instruction->as<OpNeqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_not:
        __instruction->as<OpNot>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_identity_with_profile:
        __instruction->as<OpIdentityWithProfile>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_overrides_has_instance:
        __instruction->as<OpOverridesHasInstance>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_instanceof:
        __instruction->as<OpInstanceof>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_instanceof_custom:
        __instruction->as<OpInstanceofCustom>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_typeof:
        __instruction->as<OpTypeof>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_cell_with_type:
        __instruction->as<OpIsCellWithType>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_eq_null:
        __instruction->as<OpEqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_in_by_id:
        __instruction->as<OpInById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_urshift:
        __instruction->as<OpUrshift>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_rshift:
        __instruction->as<OpRshift>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_pow:
        __instruction->as<OpPow>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_mod:
        __instruction->as<OpMod>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_beloweq:
        __instruction->as<OpBeloweq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_below:
        __instruction->as<OpBelow>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_by_id_with_this:
        __instruction->as<OpPutByIdWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_del_by_id:
        __instruction->as<OpDelById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_greatereq:
        __instruction->as<OpGreatereq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_greater:
        __instruction->as<OpGreater>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_by_val_with_this:
        __instruction->as<OpPutByValWithThis>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_lesseq:
        __instruction->as<OpLesseq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_del_by_val:
        __instruction->as<OpDelByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_getter_by_id:
        __instruction->as<OpPutGetterById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_setter_by_id:
        __instruction->as<OpPutSetterById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_getter_setter_by_id:
        __instruction->as<OpPutGetterSetterById>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_getter_by_val:
        __instruction->as<OpPutGetterByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_setter_by_val:
        __instruction->as<OpPutSetterByVal>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_define_data_property:
        __instruction->as<OpDefineDataProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_define_accessor_property:
        __instruction->as<OpDefineAccessorProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jmp:
        __instruction->as<OpJmp>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jtrue:
        __instruction->as<OpJtrue>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jfalse:
        __instruction->as<OpJfalse>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jeq_null:
        __instruction->as<OpJeqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jneq_null:
        __instruction->as<OpJneqNull>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_less:
        __instruction->as<OpLess>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jeq:
        __instruction->as<OpJeq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jstricteq:
        __instruction->as<OpJstricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jneq:
        __instruction->as<OpJneq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jnstricteq:
        __instruction->as<OpJnstricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jless:
        __instruction->as<OpJless>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jlesseq:
        __instruction->as<OpJlesseq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jgreater:
        __instruction->as<OpJgreater>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jgreatereq:
        __instruction->as<OpJgreatereq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jnless:
        __instruction->as<OpJnless>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jnlesseq:
        __instruction->as<OpJnlesseq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jngreater:
        __instruction->as<OpJngreater>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jngreatereq:
        __instruction->as<OpJngreatereq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jbelow:
        __instruction->as<OpJbelow>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_jbeloweq:
        __instruction->as<OpJbeloweq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_loop_hint:
        __instruction->as<OpLoopHint>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_switch_imm:
        __instruction->as<OpSwitchImm>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_switch_char:
        __instruction->as<OpSwitchChar>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_switch_string:
        __instruction->as<OpSwitchString>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_func:
        __instruction->as<OpNewFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_func_exp:
        __instruction->as<OpNewFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_generator_func:
        __instruction->as<OpNewGeneratorFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_generator_func_exp:
        __instruction->as<OpNewGeneratorFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_async_func:
        __instruction->as<OpNewAsyncFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_async_func_exp:
        __instruction->as<OpNewAsyncFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_async_generator_func:
        __instruction->as<OpNewAsyncGeneratorFunc>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_async_generator_func_exp:
        __instruction->as<OpNewAsyncGeneratorFuncExp>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_set_function_name:
        __instruction->as<OpSetFunctionName>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_nstricteq:
        __instruction->as<OpNstricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_stricteq:
        __instruction->as<OpStricteq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_neq:
        __instruction->as<OpNeq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_eq:
        __instruction->as<OpEq>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_is_empty:
        __instruction->as<OpIsEmpty>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_mov:
        __instruction->as<OpMov>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_regexp:
        __instruction->as<OpNewRegexp>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_spread:
        __instruction->as<OpSpread>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_ret:
        __instruction->as<OpRet>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_strcat:
        __instruction->as<OpStrcat>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_to_primitive:
        __instruction->as<OpToPrimitive>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_new_array_with_spread:
        __instruction->as<OpNewArrayWithSpread>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_check_tdz:
        __instruction->as<OpCheckTdz>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_argument_count:
        __instruction->as<OpArgumentCount>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_cloned_arguments:
        __instruction->as<OpCreateClonedArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_put_to_arguments:
        __instruction->as<OpPutToArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_push_with_scope:
        __instruction->as<OpPushWithScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_lexical_environment:
        __instruction->as<OpCreateLexicalEnvironment>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_generator_frame_environment:
        __instruction->as<OpCreateGeneratorFrameEnvironment>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_parent_scope:
        __instruction->as<OpGetParentScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_scoped_arguments:
        __instruction->as<OpCreateScopedArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_throw:
        __instruction->as<OpThrow>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_throw_static_error:
        __instruction->as<OpThrowStaticError>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_debug:
        __instruction->as<OpDebug>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_end:
        __instruction->as<OpEnd>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_direct_arguments:
        __instruction->as<OpCreateDirectArguments>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_scope:
        __instruction->as<OpGetScope>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_enumerable_length:
        __instruction->as<OpGetEnumerableLength>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_enter:
        __instruction->as<OpEnter>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_has_structure_property:
        __instruction->as<OpHasStructureProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_has_generic_property:
        __instruction->as<OpHasGenericProperty>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_wide32:
        __instruction->as<OpWide32>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_property_enumerator:
        __instruction->as<OpGetPropertyEnumerator>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_enumerator_structure_pname:
        __instruction->as<OpEnumeratorStructurePname>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_enumerator_generic_pname:
        __instruction->as<OpEnumeratorGenericPname>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_to_index_string:
        __instruction->as<OpToIndexString>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_unreachable:
        __instruction->as<OpUnreachable>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_create_rest:
        __instruction->as<OpCreateRest>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_get_rest_length:
        __instruction->as<OpGetRestLength>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_yield:
        __instruction->as<OpYield>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_check_traps:
        __instruction->as<OpCheckTraps>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_log_shadow_chicken_prologue:
        __instruction->as<OpLogShadowChickenPrologue>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_log_shadow_chicken_tail:
        __instruction->as<OpLogShadowChickenTail>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_resolve_scope_for_hoisting_func_decl_in_eval:
        __instruction->as<OpResolveScopeForHoistingFuncDeclInEval>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_nop:
        __instruction->as<OpNop>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_super_sampler_begin:
        __instruction->as<OpSuperSamplerBegin>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    case op_super_sampler_end:
        __instruction->as<OpSuperSamplerEnd>().dump(dumper, __location, __instruction->sizeShiftAmount());
        break;
    default:
        ASSERT_NOT_REACHED();
    }
}

} // namespace JSC
