Coverage Report

Created: 2025-08-28 06:26

/src/serenity/Userland/Libraries/LibJS/Bytecode/Op.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2021-2023, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
4
 * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 */
8
9
#pragma once
10
11
#include <AK/FixedArray.h>
12
#include <AK/StdLibExtras.h>
13
#include <LibCrypto/BigInt/SignedBigInteger.h>
14
#include <LibJS/Bytecode/Builtins.h>
15
#include <LibJS/Bytecode/IdentifierTable.h>
16
#include <LibJS/Bytecode/Instruction.h>
17
#include <LibJS/Bytecode/Label.h>
18
#include <LibJS/Bytecode/Operand.h>
19
#include <LibJS/Bytecode/RegexTable.h>
20
#include <LibJS/Bytecode/Register.h>
21
#include <LibJS/Bytecode/ScopedOperand.h>
22
#include <LibJS/Bytecode/StringTable.h>
23
#include <LibJS/Heap/Cell.h>
24
#include <LibJS/Runtime/Environment.h>
25
#include <LibJS/Runtime/Iterator.h>
26
#include <LibJS/Runtime/Value.h>
27
#include <LibJS/Runtime/ValueTraits.h>
28
29
namespace JS {
30
class FunctionExpression;
31
}
32
33
namespace JS::Bytecode::Op {
34
35
class CreateRestParams final : public Instruction {
36
public:
37
    CreateRestParams(Operand dst, u32 rest_index)
38
0
        : Instruction(Type::CreateRestParams)
39
0
        , m_dst(dst)
40
0
        , m_rest_index(rest_index)
41
0
    {
42
0
    }
43
44
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
45
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
46
    void visit_operands_impl(Function<void(Operand&)> visitor)
47
0
    {
48
0
        visitor(m_dst);
49
0
    }
50
51
private:
52
    Operand m_dst;
53
    u32 m_rest_index;
54
};
55
56
class CreateArguments final : public Instruction {
57
public:
58
    enum class Kind {
59
        Mapped,
60
        Unmapped,
61
    };
62
63
    CreateArguments(Optional<Operand> dst, Kind kind, bool is_immutable)
64
0
        : Instruction(Type::CreateArguments)
65
0
        , m_dst(dst)
66
0
        , m_kind(kind)
67
0
        , m_is_immutable(is_immutable)
68
0
    {
69
0
    }
70
71
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
72
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
73
    void visit_operands_impl(Function<void(Operand&)> visitor)
74
0
    {
75
0
        if (m_dst.has_value())
76
0
            visitor(m_dst.value());
77
0
    }
78
79
private:
80
    Optional<Operand> m_dst;
81
    Kind m_kind;
82
    bool m_is_immutable { false };
83
};
84
85
class Mov final : public Instruction {
86
public:
87
    Mov(Operand dst, Operand src)
88
0
        : Instruction(Type::Mov)
89
0
        , m_dst(dst)
90
0
        , m_src(src)
91
0
    {
92
0
    }
93
94
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
95
    void visit_operands_impl(Function<void(Operand&)> visitor)
96
0
    {
97
0
        visitor(m_dst);
98
0
        visitor(m_src);
99
0
    }
100
101
0
    Operand dst() const { return m_dst; }
102
0
    Operand src() const { return m_src; }
103
104
private:
105
    Operand m_dst;
106
    Operand m_src;
107
};
108
109
#define JS_ENUMERATE_COMMON_BINARY_OPS_WITH_FAST_PATH(O) \
110
    O(Add, add)                                          \
111
    O(BitwiseAnd, bitwise_and)                           \
112
    O(BitwiseOr, bitwise_or)                             \
113
    O(BitwiseXor, bitwise_xor)                           \
114
    O(GreaterThan, greater_than)                         \
115
    O(GreaterThanEquals, greater_than_equals)            \
116
    O(LeftShift, left_shift)                             \
117
    O(LessThan, less_than)                               \
118
    O(LessThanEquals, less_than_equals)                  \
119
    O(Mul, mul)                                          \
120
    O(RightShift, right_shift)                           \
121
    O(Sub, sub)                                          \
122
    O(UnsignedRightShift, unsigned_right_shift)
123
124
#define JS_ENUMERATE_COMMON_BINARY_OPS_WITHOUT_FAST_PATH(O) \
125
    O(Div, div)                                             \
126
    O(Exp, exp)                                             \
127
    O(Mod, mod)                                             \
128
    O(In, in)                                               \
129
    O(InstanceOf, instance_of)                              \
130
    O(LooselyInequals, loosely_inequals)                    \
131
    O(LooselyEquals, loosely_equals)                        \
132
    O(StrictlyInequals, strict_inequals)                    \
133
    O(StrictlyEquals, strict_equals)
134
135
#define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case)             \
136
    class OpTitleCase final : public Instruction {                          \
137
    public:                                                                 \
138
        explicit OpTitleCase(Operand dst, Operand lhs, Operand rhs)         \
139
2
            : Instruction(Type::OpTitleCase)                                \
140
2
            , m_dst(dst)                                                    \
141
2
            , m_lhs(lhs)                                                    \
142
2
            , m_rhs(rhs)                                                    \
143
2
        {                                                                   \
144
2
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::Div::Div(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::Exp::Exp(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::Mod::Mod(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::In::In(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::InstanceOf::InstanceOf(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::LooselyInequals::LooselyInequals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::LooselyEquals::LooselyEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::StrictlyInequals::StrictlyInequals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::StrictlyEquals::StrictlyEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::Add::Add(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::BitwiseAnd::BitwiseAnd(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::BitwiseOr::BitwiseOr(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::BitwiseXor::BitwiseXor(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::GreaterThan::GreaterThan(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::GreaterThanEquals::GreaterThanEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::LeftShift::LeftShift(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::LessThan::LessThan(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::LessThanEquals::LessThanEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::Mul::Mul(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::RightShift::RightShift(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
JS::Bytecode::Op::Sub::Sub(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
Line
Count
Source
139
2
            : Instruction(Type::OpTitleCase)                                \
140
2
            , m_dst(dst)                                                    \
141
2
            , m_lhs(lhs)                                                    \
142
2
            , m_rhs(rhs)                                                    \
143
2
        {                                                                   \
144
2
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::UnsignedRightShift::UnsignedRightShift(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Operand)
145
                                                                            \
146
        ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
147
        ByteString to_byte_string_impl(Bytecode::Executable const&) const;  \
148
        void visit_operands_impl(Function<void(Operand&)> visitor)          \
149
2
        {                                                                   \
150
2
            visitor(m_dst);                                                 \
151
2
            visitor(m_lhs);                                                 \
152
2
            visitor(m_rhs);                                                 \
153
2
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::Div::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::Exp::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::Mod::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::In::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::InstanceOf::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::LooselyInequals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::LooselyEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::StrictlyInequals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::StrictlyEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::Add::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::BitwiseAnd::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::BitwiseOr::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::BitwiseXor::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::GreaterThan::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::GreaterThanEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::LeftShift::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::LessThan::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::LessThanEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::Mul::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::RightShift::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
JS::Bytecode::Op::Sub::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Line
Count
Source
149
2
        {                                                                   \
150
2
            visitor(m_dst);                                                 \
151
2
            visitor(m_lhs);                                                 \
152
2
            visitor(m_rhs);                                                 \
153
2
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::UnsignedRightShift::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
154
                                                                            \
155
0
        Operand dst() const { return m_dst; }                               \
Unexecuted instantiation: JS::Bytecode::Op::Div::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Exp::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Mod::dst() const
Unexecuted instantiation: JS::Bytecode::Op::In::dst() const
Unexecuted instantiation: JS::Bytecode::Op::InstanceOf::dst() const
Unexecuted instantiation: JS::Bytecode::Op::LooselyInequals::dst() const
Unexecuted instantiation: JS::Bytecode::Op::LooselyEquals::dst() const
Unexecuted instantiation: JS::Bytecode::Op::StrictlyInequals::dst() const
Unexecuted instantiation: JS::Bytecode::Op::StrictlyEquals::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Add::dst() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseAnd::dst() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseOr::dst() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseXor::dst() const
Unexecuted instantiation: JS::Bytecode::Op::GreaterThan::dst() const
Unexecuted instantiation: JS::Bytecode::Op::GreaterThanEquals::dst() const
Unexecuted instantiation: JS::Bytecode::Op::LeftShift::dst() const
Unexecuted instantiation: JS::Bytecode::Op::LessThan::dst() const
Unexecuted instantiation: JS::Bytecode::Op::LessThanEquals::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Mul::dst() const
Unexecuted instantiation: JS::Bytecode::Op::RightShift::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Sub::dst() const
Unexecuted instantiation: JS::Bytecode::Op::UnsignedRightShift::dst() const
156
0
        Operand lhs() const { return m_lhs; }                               \
Unexecuted instantiation: JS::Bytecode::Op::Div::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::Exp::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::Mod::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::In::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::InstanceOf::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::LooselyInequals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::LooselyEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::StrictlyInequals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::StrictlyEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::Add::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseAnd::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseOr::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseXor::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::GreaterThan::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::GreaterThanEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::LeftShift::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::LessThan::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::LessThanEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::Mul::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::RightShift::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::Sub::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::UnsignedRightShift::lhs() const
157
0
        Operand rhs() const { return m_rhs; }                               \
Unexecuted instantiation: JS::Bytecode::Op::Div::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::Exp::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::Mod::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::In::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::InstanceOf::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::LooselyInequals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::LooselyEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::StrictlyInequals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::StrictlyEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::Add::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseAnd::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseOr::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::BitwiseXor::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::GreaterThan::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::GreaterThanEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::LeftShift::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::LessThan::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::LessThanEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::Mul::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::RightShift::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::Sub::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::UnsignedRightShift::rhs() const
158
                                                                            \
159
    private:                                                                \
160
        Operand m_dst;                                                      \
161
        Operand m_lhs;                                                      \
162
        Operand m_rhs;                                                      \
163
    };
164
165
JS_ENUMERATE_COMMON_BINARY_OPS_WITHOUT_FAST_PATH(JS_DECLARE_COMMON_BINARY_OP)
166
JS_ENUMERATE_COMMON_BINARY_OPS_WITH_FAST_PATH(JS_DECLARE_COMMON_BINARY_OP)
167
#undef JS_DECLARE_COMMON_BINARY_OP
168
169
#define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
170
    O(BitwiseNot, bitwise_not)           \
171
    O(Not, not_)                         \
172
    O(UnaryPlus, unary_plus)             \
173
    O(UnaryMinus, unary_minus)           \
174
    O(Typeof, typeof_)
175
176
#define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case)              \
177
    class OpTitleCase final : public Instruction {                          \
178
    public:                                                                 \
179
        OpTitleCase(Operand dst, Operand src)                               \
180
3
            : Instruction(Type::OpTitleCase)                                \
181
3
            , m_dst(dst)                                                    \
182
3
            , m_src(src)                                                    \
183
3
        {                                                                   \
184
3
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::BitwiseNot::BitwiseNot(JS::Bytecode::Operand, JS::Bytecode::Operand)
JS::Bytecode::Op::Not::Not(JS::Bytecode::Operand, JS::Bytecode::Operand)
Line
Count
Source
180
3
            : Instruction(Type::OpTitleCase)                                \
181
3
            , m_dst(dst)                                                    \
182
3
            , m_src(src)                                                    \
183
3
        {                                                                   \
184
3
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::UnaryPlus::UnaryPlus(JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::UnaryMinus::UnaryMinus(JS::Bytecode::Operand, JS::Bytecode::Operand)
Unexecuted instantiation: JS::Bytecode::Op::Typeof::Typeof(JS::Bytecode::Operand, JS::Bytecode::Operand)
185
                                                                            \
186
        ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
187
        ByteString to_byte_string_impl(Bytecode::Executable const&) const;  \
188
        void visit_operands_impl(Function<void(Operand&)> visitor)          \
189
3
        {                                                                   \
190
3
            visitor(m_dst);                                                 \
191
3
            visitor(m_src);                                                 \
192
3
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::BitwiseNot::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
JS::Bytecode::Op::Not::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Line
Count
Source
189
3
        {                                                                   \
190
3
            visitor(m_dst);                                                 \
191
3
            visitor(m_src);                                                 \
192
3
        }                                                                   \
Unexecuted instantiation: JS::Bytecode::Op::UnaryPlus::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::UnaryMinus::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::Typeof::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
193
                                                                            \
194
0
        Operand dst() const { return m_dst; }                               \
Unexecuted instantiation: JS::Bytecode::Op::BitwiseNot::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Not::dst() const
Unexecuted instantiation: JS::Bytecode::Op::UnaryPlus::dst() const
Unexecuted instantiation: JS::Bytecode::Op::UnaryMinus::dst() const
Unexecuted instantiation: JS::Bytecode::Op::Typeof::dst() const
195
0
        Operand src() const { return m_src; }                               \
Unexecuted instantiation: JS::Bytecode::Op::BitwiseNot::src() const
Unexecuted instantiation: JS::Bytecode::Op::Not::src() const
Unexecuted instantiation: JS::Bytecode::Op::UnaryPlus::src() const
Unexecuted instantiation: JS::Bytecode::Op::UnaryMinus::src() const
Unexecuted instantiation: JS::Bytecode::Op::Typeof::src() const
196
                                                                            \
197
    private:                                                                \
198
        Operand m_dst;                                                      \
199
        Operand m_src;                                                      \
200
    };
201
202
JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
203
#undef JS_DECLARE_COMMON_UNARY_OP
204
205
class NewObject final : public Instruction {
206
public:
207
    explicit NewObject(Operand dst)
208
0
        : Instruction(Type::NewObject)
209
0
        , m_dst(dst)
210
0
    {
211
0
    }
212
213
    void execute_impl(Bytecode::Interpreter&) const;
214
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
215
    void visit_operands_impl(Function<void(Operand&)> visitor)
216
0
    {
217
0
        visitor(m_dst);
218
0
    }
219
220
0
    Operand dst() const { return m_dst; }
221
222
private:
223
    Operand m_dst;
224
};
225
226
class NewRegExp final : public Instruction {
227
public:
228
    NewRegExp(Operand dst, StringTableIndex source_index, StringTableIndex flags_index, RegexTableIndex regex_index)
229
0
        : Instruction(Type::NewRegExp)
230
0
        , m_dst(dst)
231
0
        , m_source_index(source_index)
232
0
        , m_flags_index(flags_index)
233
0
        , m_regex_index(regex_index)
234
0
    {
235
0
    }
236
237
    void execute_impl(Bytecode::Interpreter&) const;
238
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
239
    void visit_operands_impl(Function<void(Operand&)> visitor)
240
0
    {
241
0
        visitor(m_dst);
242
0
    }
243
244
0
    Operand dst() const { return m_dst; }
245
0
    StringTableIndex source_index() const { return m_source_index; }
246
0
    StringTableIndex flags_index() const { return m_flags_index; }
247
0
    RegexTableIndex regex_index() const { return m_regex_index; }
248
249
private:
250
    Operand m_dst;
251
    StringTableIndex m_source_index;
252
    StringTableIndex m_flags_index;
253
    RegexTableIndex m_regex_index;
254
};
255
256
#define JS_ENUMERATE_NEW_BUILTIN_ERROR_OPS(O) \
257
    O(TypeError)
258
259
#define JS_DECLARE_NEW_BUILTIN_ERROR_OP(ErrorName)                         \
260
    class New##ErrorName final : public Instruction {                      \
261
    public:                                                                \
262
        New##ErrorName(Operand dst, StringTableIndex error_string)         \
263
0
            : Instruction(Type::New##ErrorName)                            \
264
0
            , m_dst(dst)                                                   \
265
0
            , m_error_string(error_string)                                 \
266
0
        {                                                                  \
267
0
        }                                                                  \
268
                                                                           \
269
        void execute_impl(Bytecode::Interpreter&) const;                   \
270
        ByteString to_byte_string_impl(Bytecode::Executable const&) const; \
271
        void visit_operands_impl(Function<void(Operand&)> visitor)         \
272
0
        {                                                                  \
273
0
            visitor(m_dst);                                                \
274
0
        }                                                                  \
275
                                                                           \
276
0
        Operand dst() const { return m_dst; }                              \
277
0
        StringTableIndex error_string() const { return m_error_string; }   \
278
                                                                           \
279
    private:                                                               \
280
        Operand m_dst;                                                     \
281
        StringTableIndex m_error_string;                                   \
282
    };
283
284
JS_ENUMERATE_NEW_BUILTIN_ERROR_OPS(JS_DECLARE_NEW_BUILTIN_ERROR_OP)
285
#undef JS_DECLARE_NEW_BUILTIN_ERROR_OP
286
287
// NOTE: This instruction is variable-width depending on the number of excluded names
288
class CopyObjectExcludingProperties final : public Instruction {
289
public:
290
    static constexpr bool IsVariableLength = true;
291
292
    CopyObjectExcludingProperties(Operand dst, Operand from_object, Vector<ScopedOperand> const& excluded_names)
293
0
        : Instruction(Type::CopyObjectExcludingProperties)
294
0
        , m_dst(dst)
295
0
        , m_from_object(from_object)
296
0
        , m_excluded_names_count(excluded_names.size())
297
0
    {
298
0
        for (size_t i = 0; i < m_excluded_names_count; i++)
299
0
            m_excluded_names[i] = excluded_names[i];
300
0
    }
301
302
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
303
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
304
    void visit_operands_impl(Function<void(Operand&)> visitor)
305
0
    {
306
0
        visitor(m_dst);
307
0
        visitor(m_from_object);
308
0
        for (size_t i = 0; i < m_excluded_names_count; i++)
309
0
            visitor(m_excluded_names[i]);
310
0
    }
311
312
    size_t length_impl() const
313
0
    {
314
0
        return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_excluded_names_count);
315
0
    }
316
317
0
    Operand dst() const { return m_dst; }
318
0
    Operand from_object() const { return m_from_object; }
319
0
    size_t excluded_names_count() const { return m_excluded_names_count; }
320
0
    Operand const* excluded_names() const { return m_excluded_names; }
321
322
private:
323
    Operand m_dst;
324
    Operand m_from_object;
325
    size_t m_excluded_names_count { 0 };
326
    Operand m_excluded_names[];
327
};
328
329
// NOTE: This instruction is variable-width depending on the number of elements!
330
class NewArray final : public Instruction {
331
public:
332
    static constexpr bool IsVariableLength = true;
333
334
    explicit NewArray(Operand dst)
335
0
        : Instruction(Type::NewArray)
336
0
        , m_dst(dst)
337
0
        , m_element_count(0)
338
0
    {
339
0
    }
340
341
    NewArray(Operand dst, ReadonlySpan<ScopedOperand> elements)
342
3
        : Instruction(Type::NewArray)
343
3
        , m_dst(dst)
344
3
        , m_element_count(elements.size())
345
3
    {
346
469k
        for (size_t i = 0; i < m_element_count; ++i)
347
469k
            m_elements[i] = elements[i];
348
3
    }
349
350
    void execute_impl(Bytecode::Interpreter&) const;
351
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
352
    void visit_operands_impl(Function<void(Operand&)> visitor)
353
3
    {
354
3
        visitor(m_dst);
355
469k
        for (size_t i = 0; i < m_element_count; i++)
356
469k
            visitor(m_elements[i]);
357
3
    }
358
359
3
    Operand dst() const { return m_dst; }
360
361
    size_t length_impl() const
362
15
    {
363
15
        return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_element_count);
364
15
    }
365
366
0
    size_t element_count() const { return m_element_count; }
367
368
private:
369
    Operand m_dst;
370
    size_t m_element_count { 0 };
371
    Operand m_elements[];
372
};
373
374
class NewPrimitiveArray final : public Instruction {
375
public:
376
    static constexpr bool IsVariableLength = true;
377
378
    NewPrimitiveArray(Operand dst, ReadonlySpan<Value> elements)
379
0
        : Instruction(Type::NewPrimitiveArray)
380
0
        , m_dst(dst)
381
0
        , m_element_count(elements.size())
382
0
    {
383
0
        for (size_t i = 0; i < m_element_count; ++i)
384
0
            m_elements[i] = elements[i];
385
0
    }
386
387
    size_t length_impl() const
388
0
    {
389
0
        return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Value) * m_element_count);
390
0
    }
391
392
    void execute_impl(Bytecode::Interpreter&) const;
393
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
394
    void visit_operands_impl(Function<void(Operand&)> visitor)
395
0
    {
396
0
        visitor(m_dst);
397
0
    }
398
399
0
    Operand dst() const { return m_dst; }
400
0
    ReadonlySpan<Value> elements() const { return { m_elements, m_element_count }; }
401
402
private:
403
    Operand m_dst;
404
    size_t m_element_count { 0 };
405
    Value m_elements[];
406
};
407
408
class AddPrivateName final : public Instruction {
409
public:
410
    explicit AddPrivateName(IdentifierTableIndex name)
411
0
        : Instruction(Type::AddPrivateName)
412
0
        , m_name(name)
413
0
    {
414
0
    }
415
416
    void execute_impl(Bytecode::Interpreter&) const;
417
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
418
419
private:
420
    IdentifierTableIndex m_name;
421
};
422
423
class ArrayAppend final : public Instruction {
424
public:
425
    ArrayAppend(Operand dst, Operand src, bool is_spread)
426
0
        : Instruction(Type::ArrayAppend)
427
0
        , m_dst(dst)
428
0
        , m_src(src)
429
0
        , m_is_spread(is_spread)
430
0
    {
431
0
    }
432
433
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
434
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
435
    void visit_operands_impl(Function<void(Operand&)> visitor)
436
0
    {
437
0
        visitor(m_dst);
438
0
        visitor(m_src);
439
0
    }
440
441
0
    Operand dst() const { return m_dst; }
442
0
    Operand src() const { return m_src; }
443
0
    bool is_spread() const { return m_is_spread; }
444
445
private:
446
    Operand m_dst;
447
    Operand m_src;
448
    bool m_is_spread = false;
449
};
450
451
class ImportCall final : public Instruction {
452
public:
453
    ImportCall(Operand dst, Operand specifier, Operand options)
454
0
        : Instruction(Type::ImportCall)
455
0
        , m_dst(dst)
456
0
        , m_specifier(specifier)
457
0
        , m_options(options)
458
0
    {
459
0
    }
460
461
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
462
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
463
    void visit_operands_impl(Function<void(Operand&)> visitor)
464
0
    {
465
0
        visitor(m_dst);
466
0
        visitor(m_specifier);
467
0
        visitor(m_options);
468
0
    }
469
470
0
    Operand dst() const { return m_dst; }
471
0
    Operand specifier() const { return m_specifier; }
472
0
    Operand options() const { return m_options; }
473
474
private:
475
    Operand m_dst;
476
    Operand m_specifier;
477
    Operand m_options;
478
};
479
480
class IteratorToArray final : public Instruction {
481
public:
482
    explicit IteratorToArray(Operand dst, Operand iterator)
483
0
        : Instruction(Type::IteratorToArray)
484
0
        , m_dst(dst)
485
0
        , m_iterator(iterator)
486
0
    {
487
0
    }
488
489
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
490
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
491
492
0
    Operand dst() const { return m_dst; }
493
0
    Operand iterator() const { return m_iterator; }
494
495
    void visit_operands_impl(Function<void(Operand&)> visitor)
496
0
    {
497
0
        visitor(m_dst);
498
0
        visitor(m_iterator);
499
0
    }
500
501
private:
502
    Operand m_dst;
503
    Operand m_iterator;
504
};
505
506
class ConcatString final : public Instruction {
507
public:
508
    explicit ConcatString(Operand dst, Operand src)
509
0
        : Instruction(Type::ConcatString)
510
0
        , m_dst(dst)
511
0
        , m_src(src)
512
0
    {
513
0
    }
514
515
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
516
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
517
518
0
    Operand dst() const { return m_dst; }
519
0
    Operand src() const { return m_src; }
520
521
    void visit_operands_impl(Function<void(Operand&)> visitor)
522
0
    {
523
0
        visitor(m_dst);
524
0
        visitor(m_src);
525
0
    }
526
527
private:
528
    Operand m_dst;
529
    Operand m_src;
530
};
531
532
enum class EnvironmentMode {
533
    Lexical,
534
    Var,
535
};
536
537
enum class BindingInitializationMode {
538
    Initialize,
539
    Set,
540
};
541
542
class CreateLexicalEnvironment final : public Instruction {
543
public:
544
    explicit CreateLexicalEnvironment(u32 capacity = 0)
545
0
        : Instruction(Type::CreateLexicalEnvironment)
546
0
        , m_capacity(capacity)
547
0
    {
548
0
    }
549
550
    void execute_impl(Bytecode::Interpreter&) const;
551
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
552
553
private:
554
    u32 m_capacity { 0 };
555
};
556
557
class CreateVariableEnvironment final : public Instruction {
558
public:
559
    explicit CreateVariableEnvironment(u32 capacity = 0)
560
0
        : Instruction(Type::CreateVariableEnvironment)
561
0
        , m_capacity(capacity)
562
0
    {
563
0
    }
564
565
    void execute_impl(Bytecode::Interpreter&) const;
566
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
567
568
private:
569
    u32 m_capacity { 0 };
570
};
571
572
class CreatePrivateEnvironment final : public Instruction {
573
public:
574
    explicit CreatePrivateEnvironment()
575
0
        : Instruction(Type::CreatePrivateEnvironment)
576
0
    {
577
0
    }
578
579
    void execute_impl(Bytecode::Interpreter&) const;
580
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
581
};
582
583
class EnterObjectEnvironment final : public Instruction {
584
public:
585
    explicit EnterObjectEnvironment(Operand object)
586
0
        : Instruction(Type::EnterObjectEnvironment)
587
0
        , m_object(object)
588
0
    {
589
0
    }
590
591
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
592
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
593
594
0
    Operand object() const { return m_object; }
595
596
    void visit_operands_impl(Function<void(Operand&)> visitor)
597
0
    {
598
0
        visitor(m_object);
599
0
    }
600
601
private:
602
    Operand m_object;
603
};
604
605
class Catch final : public Instruction {
606
public:
607
    explicit Catch(Operand dst)
608
0
        : Instruction(Type::Catch)
609
0
        , m_dst(dst)
610
0
    {
611
0
    }
612
613
    void execute_impl(Bytecode::Interpreter&) const;
614
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
615
616
0
    Operand dst() const { return m_dst; }
617
618
    void visit_operands_impl(Function<void(Operand&)> visitor)
619
0
    {
620
0
        visitor(m_dst);
621
0
    }
622
623
private:
624
    Operand m_dst;
625
};
626
627
class LeaveFinally final : public Instruction {
628
public:
629
    explicit LeaveFinally()
630
0
        : Instruction(Type::LeaveFinally)
631
0
    {
632
0
    }
633
634
    void execute_impl(Bytecode::Interpreter&) const;
635
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
636
};
637
638
class RestoreScheduledJump final : public Instruction {
639
public:
640
    explicit RestoreScheduledJump()
641
0
        : Instruction(Type::RestoreScheduledJump)
642
0
    {
643
0
    }
644
645
    void execute_impl(Bytecode::Interpreter&) const;
646
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
647
};
648
649
class CreateVariable final : public Instruction {
650
public:
651
    explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable, bool is_global = false, bool is_strict = false)
652
0
        : Instruction(Type::CreateVariable)
653
0
        , m_identifier(identifier)
654
0
        , m_mode(mode)
655
0
        , m_is_immutable(is_immutable)
656
0
        , m_is_global(is_global)
657
0
        , m_is_strict(is_strict)
658
0
    {
659
0
    }
660
661
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
662
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
663
664
0
    IdentifierTableIndex identifier() const { return m_identifier; }
665
0
    EnvironmentMode mode() const { return m_mode; }
666
0
    bool is_immutable() const { return m_is_immutable; }
667
0
    bool is_global() const { return m_is_global; }
668
0
    bool is_strict() const { return m_is_strict; }
669
670
private:
671
    IdentifierTableIndex m_identifier;
672
    EnvironmentMode m_mode;
673
    bool m_is_immutable : 4 { false };
674
    bool m_is_global : 4 { false };
675
    bool m_is_strict { false };
676
};
677
678
class InitializeLexicalBinding final : public Instruction {
679
public:
680
    explicit InitializeLexicalBinding(IdentifierTableIndex identifier, Operand src)
681
0
        : Instruction(Type::InitializeLexicalBinding)
682
0
        , m_identifier(identifier)
683
0
        , m_src(src)
684
0
    {
685
0
    }
686
687
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
688
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
689
    void visit_operands_impl(Function<void(Operand&)> visitor)
690
0
    {
691
0
        visitor(m_src);
692
0
    }
693
694
0
    IdentifierTableIndex identifier() const { return m_identifier; }
695
0
    Operand src() const { return m_src; }
696
697
private:
698
    IdentifierTableIndex m_identifier;
699
    Operand m_src;
700
    mutable EnvironmentCoordinate m_cache;
701
};
702
703
class InitializeVariableBinding final : public Instruction {
704
public:
705
    explicit InitializeVariableBinding(IdentifierTableIndex identifier, Operand src)
706
0
        : Instruction(Type::InitializeVariableBinding)
707
0
        , m_identifier(identifier)
708
0
        , m_src(src)
709
0
    {
710
0
    }
711
712
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
713
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
714
    void visit_operands_impl(Function<void(Operand&)> visitor)
715
0
    {
716
0
        visitor(m_src);
717
0
    }
718
719
0
    IdentifierTableIndex identifier() const { return m_identifier; }
720
0
    Operand src() const { return m_src; }
721
722
private:
723
    IdentifierTableIndex m_identifier;
724
    Operand m_src;
725
    mutable EnvironmentCoordinate m_cache;
726
};
727
728
class SetLexicalBinding final : public Instruction {
729
public:
730
    explicit SetLexicalBinding(IdentifierTableIndex identifier, Operand src)
731
0
        : Instruction(Type::SetLexicalBinding)
732
0
        , m_identifier(identifier)
733
0
        , m_src(src)
734
0
    {
735
0
    }
736
737
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
738
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
739
    void visit_operands_impl(Function<void(Operand&)> visitor)
740
0
    {
741
0
        visitor(m_src);
742
0
    }
743
744
0
    IdentifierTableIndex identifier() const { return m_identifier; }
745
0
    Operand src() const { return m_src; }
746
747
private:
748
    IdentifierTableIndex m_identifier;
749
    Operand m_src;
750
    mutable EnvironmentCoordinate m_cache;
751
};
752
753
class SetVariableBinding final : public Instruction {
754
public:
755
    explicit SetVariableBinding(IdentifierTableIndex identifier, Operand src)
756
0
        : Instruction(Type::SetVariableBinding)
757
0
        , m_identifier(identifier)
758
0
        , m_src(src)
759
0
    {
760
0
    }
761
762
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
763
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
764
    void visit_operands_impl(Function<void(Operand&)> visitor)
765
0
    {
766
0
        visitor(m_src);
767
0
    }
768
769
0
    IdentifierTableIndex identifier() const { return m_identifier; }
770
0
    Operand src() const { return m_src; }
771
772
private:
773
    IdentifierTableIndex m_identifier;
774
    Operand m_src;
775
    mutable EnvironmentCoordinate m_cache;
776
};
777
778
class SetArgument final : public Instruction {
779
public:
780
    SetArgument(size_t index, Operand src)
781
0
        : Instruction(Type::SetArgument)
782
0
        , m_index(index)
783
0
        , m_src(src)
784
0
    {
785
0
    }
786
787
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
788
    void visit_operands_impl(Function<void(Operand&)> visitor)
789
0
    {
790
0
        visitor(m_src);
791
0
    }
792
793
0
    size_t index() const { return m_index; }
794
0
    Operand src() const { return m_src; }
795
796
private:
797
    u32 m_index;
798
    Operand m_src;
799
};
800
801
class GetArgument final : public Instruction {
802
public:
803
    GetArgument(Operand dst, size_t index)
804
0
        : Instruction(Type::GetArgument)
805
0
        , m_index(index)
806
0
        , m_dst(dst)
807
0
    {
808
0
    }
809
810
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
811
    void visit_operands_impl(Function<void(Operand&)> visitor)
812
0
    {
813
0
        visitor(m_dst);
814
0
    }
815
816
0
    u32 index() const { return m_index; }
817
0
    Operand dst() const { return m_dst; }
818
819
private:
820
    u32 m_index;
821
    Operand m_dst;
822
};
823
824
class GetCalleeAndThisFromEnvironment final : public Instruction {
825
public:
826
    explicit GetCalleeAndThisFromEnvironment(Operand callee, Operand this_value, IdentifierTableIndex identifier)
827
0
        : Instruction(Type::GetCalleeAndThisFromEnvironment)
828
0
        , m_identifier(identifier)
829
0
        , m_callee(callee)
830
0
        , m_this_value(this_value)
831
0
    {
832
0
    }
833
834
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
835
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
836
    void visit_operands_impl(Function<void(Operand&)> visitor)
837
0
    {
838
0
        visitor(m_callee);
839
0
        visitor(m_this_value);
840
0
    }
841
842
0
    IdentifierTableIndex identifier() const { return m_identifier; }
843
0
    Operand callee() const { return m_callee; }
844
0
    Operand this_() const { return m_this_value; }
845
846
private:
847
    IdentifierTableIndex m_identifier;
848
    Operand m_callee;
849
    Operand m_this_value;
850
    mutable EnvironmentCoordinate m_cache;
851
};
852
853
class GetBinding final : public Instruction {
854
public:
855
    explicit GetBinding(Operand dst, IdentifierTableIndex identifier)
856
0
        : Instruction(Type::GetBinding)
857
0
        , m_dst(dst)
858
0
        , m_identifier(identifier)
859
0
    {
860
0
    }
861
862
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
863
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
864
865
0
    Operand dst() const { return m_dst; }
866
0
    IdentifierTableIndex identifier() const { return m_identifier; }
867
868
    void visit_operands_impl(Function<void(Operand&)> visitor)
869
0
    {
870
0
        visitor(m_dst);
871
0
    }
872
873
private:
874
    Operand m_dst;
875
    IdentifierTableIndex m_identifier;
876
    mutable EnvironmentCoordinate m_cache;
877
};
878
879
class GetGlobal final : public Instruction {
880
public:
881
    GetGlobal(Operand dst, IdentifierTableIndex identifier, u32 cache_index)
882
9
        : Instruction(Type::GetGlobal)
883
9
        , m_dst(dst)
884
9
        , m_identifier(identifier)
885
9
        , m_cache_index(cache_index)
886
9
    {
887
9
    }
888
889
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
890
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
891
892
9
    Operand dst() const { return m_dst; }
893
0
    IdentifierTableIndex identifier() const { return m_identifier; }
894
0
    u32 cache_index() const { return m_cache_index; }
895
896
    void visit_operands_impl(Function<void(Operand&)> visitor)
897
9
    {
898
9
        visitor(m_dst);
899
9
    }
900
901
private:
902
    Operand m_dst;
903
    IdentifierTableIndex m_identifier;
904
    u32 m_cache_index { 0 };
905
};
906
907
class DeleteVariable final : public Instruction {
908
public:
909
    explicit DeleteVariable(Operand dst, IdentifierTableIndex identifier)
910
0
        : Instruction(Type::DeleteVariable)
911
0
        , m_dst(dst)
912
0
        , m_identifier(identifier)
913
0
    {
914
0
    }
915
916
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
917
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
918
919
0
    Operand dst() const { return m_dst; }
920
0
    IdentifierTableIndex identifier() const { return m_identifier; }
921
922
    void visit_operands_impl(Function<void(Operand&)> visitor)
923
0
    {
924
0
        visitor(m_dst);
925
0
    }
926
927
private:
928
    Operand m_dst;
929
    IdentifierTableIndex m_identifier;
930
};
931
932
class GetById final : public Instruction {
933
public:
934
    GetById(Operand dst, Operand base, IdentifierTableIndex property, Optional<IdentifierTableIndex> base_identifier, u32 cache_index)
935
0
        : Instruction(Type::GetById)
936
0
        , m_dst(dst)
937
0
        , m_base(base)
938
0
        , m_property(property)
939
0
        , m_base_identifier(move(base_identifier))
940
0
        , m_cache_index(cache_index)
941
0
    {
942
0
    }
943
944
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
945
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
946
    void visit_operands_impl(Function<void(Operand&)> visitor)
947
0
    {
948
0
        visitor(m_dst);
949
0
        visitor(m_base);
950
0
    }
951
952
0
    Operand dst() const { return m_dst; }
953
0
    Operand base() const { return m_base; }
954
0
    IdentifierTableIndex property() const { return m_property; }
955
0
    u32 cache_index() const { return m_cache_index; }
956
957
private:
958
    Operand m_dst;
959
    Operand m_base;
960
    IdentifierTableIndex m_property;
961
    Optional<IdentifierTableIndex> m_base_identifier;
962
    u32 m_cache_index { 0 };
963
};
964
965
class GetByIdWithThis final : public Instruction {
966
public:
967
    GetByIdWithThis(Operand dst, Operand base, IdentifierTableIndex property, Operand this_value, u32 cache_index)
968
0
        : Instruction(Type::GetByIdWithThis)
969
0
        , m_dst(dst)
970
0
        , m_base(base)
971
0
        , m_property(property)
972
0
        , m_this_value(this_value)
973
0
        , m_cache_index(cache_index)
974
0
    {
975
0
    }
976
977
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
978
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
979
    void visit_operands_impl(Function<void(Operand&)> visitor)
980
0
    {
981
0
        visitor(m_dst);
982
0
        visitor(m_base);
983
0
        visitor(m_this_value);
984
0
    }
985
986
0
    Operand dst() const { return m_dst; }
987
0
    Operand base() const { return m_base; }
988
0
    IdentifierTableIndex property() const { return m_property; }
989
0
    Operand this_value() const { return m_this_value; }
990
0
    u32 cache_index() const { return m_cache_index; }
991
992
private:
993
    Operand m_dst;
994
    Operand m_base;
995
    IdentifierTableIndex m_property;
996
    Operand m_this_value;
997
    u32 m_cache_index { 0 };
998
};
999
1000
class GetLength final : public Instruction {
1001
public:
1002
    GetLength(Operand dst, Operand base, Optional<IdentifierTableIndex> base_identifier, u32 cache_index)
1003
0
        : Instruction(Type::GetLength)
1004
0
        , m_dst(dst)
1005
0
        , m_base(base)
1006
0
        , m_base_identifier(move(base_identifier))
1007
0
        , m_cache_index(cache_index)
1008
0
    {
1009
0
    }
1010
1011
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1012
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1013
    void visit_operands_impl(Function<void(Operand&)> visitor)
1014
0
    {
1015
0
        visitor(m_dst);
1016
0
        visitor(m_base);
1017
0
    }
1018
1019
0
    Operand dst() const { return m_dst; }
1020
0
    Operand base() const { return m_base; }
1021
0
    u32 cache_index() const { return m_cache_index; }
1022
1023
private:
1024
    Operand m_dst;
1025
    Operand m_base;
1026
    Optional<IdentifierTableIndex> m_base_identifier;
1027
    u32 m_cache_index { 0 };
1028
};
1029
1030
class GetLengthWithThis final : public Instruction {
1031
public:
1032
    GetLengthWithThis(Operand dst, Operand base, Operand this_value, u32 cache_index)
1033
0
        : Instruction(Type::GetLengthWithThis)
1034
0
        , m_dst(dst)
1035
0
        , m_base(base)
1036
0
        , m_this_value(this_value)
1037
0
        , m_cache_index(cache_index)
1038
0
    {
1039
0
    }
1040
1041
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1042
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1043
    void visit_operands_impl(Function<void(Operand&)> visitor)
1044
0
    {
1045
0
        visitor(m_dst);
1046
0
        visitor(m_base);
1047
0
        visitor(m_this_value);
1048
0
    }
1049
1050
0
    Operand dst() const { return m_dst; }
1051
0
    Operand base() const { return m_base; }
1052
0
    Operand this_value() const { return m_this_value; }
1053
0
    u32 cache_index() const { return m_cache_index; }
1054
1055
private:
1056
    Operand m_dst;
1057
    Operand m_base;
1058
    Operand m_this_value;
1059
    u32 m_cache_index { 0 };
1060
};
1061
1062
class GetPrivateById final : public Instruction {
1063
public:
1064
    explicit GetPrivateById(Operand dst, Operand base, IdentifierTableIndex property)
1065
0
        : Instruction(Type::GetPrivateById)
1066
0
        , m_dst(dst)
1067
0
        , m_base(base)
1068
0
        , m_property(property)
1069
0
    {
1070
0
    }
1071
1072
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1073
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1074
    void visit_operands_impl(Function<void(Operand&)> visitor)
1075
0
    {
1076
0
        visitor(m_dst);
1077
0
        visitor(m_base);
1078
0
    }
1079
1080
0
    Operand dst() const { return m_dst; }
1081
0
    Operand base() const { return m_base; }
1082
0
    IdentifierTableIndex property() const { return m_property; }
1083
1084
private:
1085
    Operand m_dst;
1086
    Operand m_base;
1087
    IdentifierTableIndex m_property;
1088
};
1089
1090
class HasPrivateId final : public Instruction {
1091
public:
1092
    HasPrivateId(Operand dst, Operand base, IdentifierTableIndex property)
1093
0
        : Instruction(Type::HasPrivateId)
1094
0
        , m_dst(dst)
1095
0
        , m_base(base)
1096
0
        , m_property(property)
1097
0
    {
1098
0
    }
1099
1100
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1101
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1102
    void visit_operands_impl(Function<void(Operand&)> visitor)
1103
0
    {
1104
0
        visitor(m_dst);
1105
0
        visitor(m_base);
1106
0
    }
1107
1108
0
    Operand dst() const { return m_dst; }
1109
0
    Operand base() const { return m_base; }
1110
0
    IdentifierTableIndex property() const { return m_property; }
1111
1112
private:
1113
    Operand m_dst;
1114
    Operand m_base;
1115
    IdentifierTableIndex m_property;
1116
};
1117
1118
enum class PropertyKind {
1119
    Getter,
1120
    Setter,
1121
    KeyValue,
1122
    DirectKeyValue, // Used for Object expressions. Always sets an own property, never calls a setter.
1123
    Spread,
1124
    ProtoSetter,
1125
};
1126
1127
class PutById final : public Instruction {
1128
public:
1129
    explicit PutById(Operand base, IdentifierTableIndex property, Operand src, PropertyKind kind, u32 cache_index, Optional<IdentifierTableIndex> base_identifier = {})
1130
0
        : Instruction(Type::PutById)
1131
0
        , m_base(base)
1132
0
        , m_property(property)
1133
0
        , m_src(src)
1134
0
        , m_kind(kind)
1135
0
        , m_cache_index(cache_index)
1136
0
        , m_base_identifier(move(base_identifier))
1137
0
    {
1138
0
    }
1139
1140
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1141
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1142
    void visit_operands_impl(Function<void(Operand&)> visitor)
1143
0
    {
1144
0
        visitor(m_base);
1145
0
        visitor(m_src);
1146
0
    }
1147
1148
0
    Operand base() const { return m_base; }
1149
0
    IdentifierTableIndex property() const { return m_property; }
1150
0
    Operand src() const { return m_src; }
1151
0
    PropertyKind kind() const { return m_kind; }
1152
0
    u32 cache_index() const { return m_cache_index; }
1153
1154
private:
1155
    Operand m_base;
1156
    IdentifierTableIndex m_property;
1157
    Operand m_src;
1158
    PropertyKind m_kind;
1159
    u32 m_cache_index { 0 };
1160
    Optional<IdentifierTableIndex> m_base_identifier {};
1161
};
1162
1163
class PutByIdWithThis final : public Instruction {
1164
public:
1165
    PutByIdWithThis(Operand base, Operand this_value, IdentifierTableIndex property, Operand src, PropertyKind kind, u32 cache_index)
1166
0
        : Instruction(Type::PutByIdWithThis)
1167
0
        , m_base(base)
1168
0
        , m_this_value(this_value)
1169
0
        , m_property(property)
1170
0
        , m_src(src)
1171
0
        , m_kind(kind)
1172
0
        , m_cache_index(cache_index)
1173
0
    {
1174
0
    }
1175
1176
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1177
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1178
    void visit_operands_impl(Function<void(Operand&)> visitor)
1179
0
    {
1180
0
        visitor(m_base);
1181
0
        visitor(m_this_value);
1182
0
        visitor(m_src);
1183
0
    }
1184
1185
0
    Operand base() const { return m_base; }
1186
0
    Operand this_value() const { return m_this_value; }
1187
0
    IdentifierTableIndex property() const { return m_property; }
1188
0
    Operand src() const { return m_src; }
1189
0
    PropertyKind kind() const { return m_kind; }
1190
0
    u32 cache_index() const { return m_cache_index; }
1191
1192
private:
1193
    Operand m_base;
1194
    Operand m_this_value;
1195
    IdentifierTableIndex m_property;
1196
    Operand m_src;
1197
    PropertyKind m_kind;
1198
    u32 m_cache_index { 0 };
1199
};
1200
1201
class PutPrivateById final : public Instruction {
1202
public:
1203
    explicit PutPrivateById(Operand base, IdentifierTableIndex property, Operand src, PropertyKind kind = PropertyKind::KeyValue)
1204
0
        : Instruction(Type::PutPrivateById)
1205
0
        , m_base(base)
1206
0
        , m_property(property)
1207
0
        , m_src(src)
1208
0
        , m_kind(kind)
1209
0
    {
1210
0
    }
1211
1212
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1213
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1214
    void visit_operands_impl(Function<void(Operand&)> visitor)
1215
0
    {
1216
0
        visitor(m_base);
1217
0
        visitor(m_src);
1218
0
    }
1219
1220
0
    Operand base() const { return m_base; }
1221
0
    IdentifierTableIndex property() const { return m_property; }
1222
0
    Operand src() const { return m_src; }
1223
1224
private:
1225
    Operand m_base;
1226
    IdentifierTableIndex m_property;
1227
    Operand m_src;
1228
    PropertyKind m_kind;
1229
};
1230
1231
class DeleteById final : public Instruction {
1232
public:
1233
    explicit DeleteById(Operand dst, Operand base, IdentifierTableIndex property)
1234
0
        : Instruction(Type::DeleteById)
1235
0
        , m_dst(dst)
1236
0
        , m_base(base)
1237
0
        , m_property(property)
1238
0
    {
1239
0
    }
1240
1241
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1242
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1243
    void visit_operands_impl(Function<void(Operand&)> visitor)
1244
0
    {
1245
0
        visitor(m_dst);
1246
0
        visitor(m_base);
1247
0
    }
1248
1249
0
    Operand dst() const { return m_dst; }
1250
0
    Operand base() const { return m_base; }
1251
0
    IdentifierTableIndex property() const { return m_property; }
1252
1253
private:
1254
    Operand m_dst;
1255
    Operand m_base;
1256
    IdentifierTableIndex m_property;
1257
};
1258
1259
class DeleteByIdWithThis final : public Instruction {
1260
public:
1261
    DeleteByIdWithThis(Operand dst, Operand base, Operand this_value, IdentifierTableIndex property)
1262
0
        : Instruction(Type::DeleteByIdWithThis)
1263
0
        , m_dst(dst)
1264
0
        , m_base(base)
1265
0
        , m_this_value(this_value)
1266
0
        , m_property(property)
1267
0
    {
1268
0
    }
1269
1270
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1271
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1272
    void visit_operands_impl(Function<void(Operand&)> visitor)
1273
0
    {
1274
0
        visitor(m_dst);
1275
0
        visitor(m_base);
1276
0
        visitor(m_this_value);
1277
0
    }
1278
1279
0
    Operand dst() const { return m_dst; }
1280
0
    Operand base() const { return m_base; }
1281
0
    Operand this_value() const { return m_this_value; }
1282
0
    IdentifierTableIndex property() const { return m_property; }
1283
1284
private:
1285
    Operand m_dst;
1286
    Operand m_base;
1287
    Operand m_this_value;
1288
    IdentifierTableIndex m_property;
1289
};
1290
1291
class GetByValue final : public Instruction {
1292
public:
1293
    GetByValue(Operand dst, Operand base, Operand property, Optional<IdentifierTableIndex> base_identifier = {})
1294
0
        : Instruction(Type::GetByValue)
1295
0
        , m_dst(dst)
1296
0
        , m_base(base)
1297
0
        , m_property(property)
1298
0
        , m_base_identifier(move(base_identifier))
1299
0
    {
1300
0
    }
1301
1302
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1303
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1304
    void visit_operands_impl(Function<void(Operand&)> visitor)
1305
0
    {
1306
0
        visitor(m_dst);
1307
0
        visitor(m_base);
1308
0
        visitor(m_property);
1309
0
    }
1310
1311
0
    Operand dst() const { return m_dst; }
1312
0
    Operand base() const { return m_base; }
1313
0
    Operand property() const { return m_property; }
1314
1315
    Optional<DeprecatedFlyString const&> base_identifier(Bytecode::Interpreter const&) const;
1316
1317
private:
1318
    Operand m_dst;
1319
    Operand m_base;
1320
    Operand m_property;
1321
    Optional<IdentifierTableIndex> m_base_identifier;
1322
};
1323
1324
class GetByValueWithThis final : public Instruction {
1325
public:
1326
    GetByValueWithThis(Operand dst, Operand base, Operand property, Operand this_value)
1327
0
        : Instruction(Type::GetByValueWithThis)
1328
0
        , m_dst(dst)
1329
0
        , m_base(base)
1330
0
        , m_property(property)
1331
0
        , m_this_value(this_value)
1332
0
    {
1333
0
    }
1334
1335
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1336
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1337
    void visit_operands_impl(Function<void(Operand&)> visitor)
1338
0
    {
1339
0
        visitor(m_dst);
1340
0
        visitor(m_base);
1341
0
        visitor(m_property);
1342
0
        visitor(m_this_value);
1343
0
    }
1344
1345
0
    Operand dst() const { return m_dst; }
1346
0
    Operand base() const { return m_base; }
1347
0
    Operand property() const { return m_property; }
1348
0
    Operand this_value() const { return m_this_value; }
1349
1350
private:
1351
    Operand m_dst;
1352
    Operand m_base;
1353
    Operand m_property;
1354
    Operand m_this_value;
1355
};
1356
1357
class PutByValue final : public Instruction {
1358
public:
1359
    PutByValue(Operand base, Operand property, Operand src, PropertyKind kind = PropertyKind::KeyValue, Optional<IdentifierTableIndex> base_identifier = {})
1360
0
        : Instruction(Type::PutByValue)
1361
0
        , m_base(base)
1362
0
        , m_property(property)
1363
0
        , m_src(src)
1364
0
        , m_kind(kind)
1365
0
        , m_base_identifier(move(base_identifier))
1366
0
    {
1367
0
    }
1368
1369
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1370
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1371
    void visit_operands_impl(Function<void(Operand&)> visitor)
1372
0
    {
1373
0
        visitor(m_base);
1374
0
        visitor(m_property);
1375
0
        visitor(m_src);
1376
0
    }
1377
1378
0
    Operand base() const { return m_base; }
1379
0
    Operand property() const { return m_property; }
1380
0
    Operand src() const { return m_src; }
1381
0
    PropertyKind kind() const { return m_kind; }
1382
1383
private:
1384
    Operand m_base;
1385
    Operand m_property;
1386
    Operand m_src;
1387
    PropertyKind m_kind;
1388
    Optional<IdentifierTableIndex> m_base_identifier;
1389
};
1390
1391
class PutByValueWithThis final : public Instruction {
1392
public:
1393
    PutByValueWithThis(Operand base, Operand property, Operand this_value, Operand src, PropertyKind kind = PropertyKind::KeyValue)
1394
0
        : Instruction(Type::PutByValueWithThis)
1395
0
        , m_base(base)
1396
0
        , m_property(property)
1397
0
        , m_this_value(this_value)
1398
0
        , m_src(src)
1399
0
        , m_kind(kind)
1400
0
    {
1401
0
    }
1402
1403
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1404
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1405
    void visit_operands_impl(Function<void(Operand&)> visitor)
1406
0
    {
1407
0
        visitor(m_base);
1408
0
        visitor(m_property);
1409
0
        visitor(m_this_value);
1410
0
        visitor(m_src);
1411
0
    }
1412
1413
0
    Operand base() const { return m_base; }
1414
0
    Operand property() const { return m_property; }
1415
0
    Operand this_value() const { return m_this_value; }
1416
0
    Operand src() const { return m_src; }
1417
0
    PropertyKind kind() const { return m_kind; }
1418
1419
private:
1420
    Operand m_base;
1421
    Operand m_property;
1422
    Operand m_this_value;
1423
    Operand m_src;
1424
    PropertyKind m_kind;
1425
};
1426
1427
class DeleteByValue final : public Instruction {
1428
public:
1429
    DeleteByValue(Operand dst, Operand base, Operand property)
1430
0
        : Instruction(Type::DeleteByValue)
1431
0
        , m_dst(dst)
1432
0
        , m_base(base)
1433
0
        , m_property(property)
1434
0
    {
1435
0
    }
1436
1437
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1438
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1439
    void visit_operands_impl(Function<void(Operand&)> visitor)
1440
0
    {
1441
0
        visitor(m_dst);
1442
0
        visitor(m_base);
1443
0
        visitor(m_property);
1444
0
    }
1445
1446
0
    Operand dst() const { return m_dst; }
1447
0
    Operand base() const { return m_base; }
1448
0
    Operand property() const { return m_property; }
1449
1450
private:
1451
    Operand m_dst;
1452
    Operand m_base;
1453
    Operand m_property;
1454
};
1455
1456
class DeleteByValueWithThis final : public Instruction {
1457
public:
1458
    DeleteByValueWithThis(Operand dst, Operand base, Operand this_value, Operand property)
1459
0
        : Instruction(Type::DeleteByValueWithThis)
1460
0
        , m_dst(dst)
1461
0
        , m_base(base)
1462
0
        , m_this_value(this_value)
1463
0
        , m_property(property)
1464
0
    {
1465
0
    }
1466
1467
0
    Operand dst() const { return m_dst; }
1468
0
    Operand base() const { return m_base; }
1469
0
    Operand this_value() const { return m_this_value; }
1470
0
    Operand property() const { return m_property; }
1471
1472
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1473
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1474
    void visit_operands_impl(Function<void(Operand&)> visitor)
1475
0
    {
1476
0
        visitor(m_dst);
1477
0
        visitor(m_base);
1478
0
        visitor(m_this_value);
1479
0
        visitor(m_property);
1480
0
    }
1481
1482
private:
1483
    Operand m_dst;
1484
    Operand m_base;
1485
    Operand m_this_value;
1486
    Operand m_property;
1487
};
1488
1489
class Jump final : public Instruction {
1490
public:
1491
    constexpr static bool IsTerminator = true;
1492
1493
    explicit Jump(Label target)
1494
4
        : Instruction(Type::Jump)
1495
4
        , m_target(target)
1496
4
    {
1497
4
    }
1498
1499
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1500
    void visit_labels_impl(Function<void(Label&)> visitor)
1501
0
    {
1502
0
        visitor(m_target);
1503
0
    }
1504
1505
4
    auto& target() const { return m_target; }
1506
1507
protected:
1508
    Label m_target;
1509
};
1510
1511
class JumpIf final : public Instruction {
1512
public:
1513
    constexpr static bool IsTerminator = true;
1514
1515
    explicit JumpIf(Operand condition, Label true_target, Label false_target)
1516
0
        : Instruction(Type::JumpIf)
1517
0
        , m_condition(condition)
1518
0
        , m_true_target(true_target)
1519
0
        , m_false_target(false_target)
1520
0
    {
1521
0
    }
1522
1523
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1524
    void visit_labels_impl(Function<void(Label&)> visitor)
1525
0
    {
1526
0
        visitor(m_true_target);
1527
0
        visitor(m_false_target);
1528
0
    }
1529
    void visit_operands_impl(Function<void(Operand&)> visitor)
1530
0
    {
1531
0
        visitor(m_condition);
1532
0
    }
1533
1534
0
    Operand condition() const { return m_condition; }
1535
0
    auto& true_target() const { return m_true_target; }
1536
0
    auto& false_target() const { return m_false_target; }
1537
1538
private:
1539
    Operand m_condition;
1540
    Label m_true_target;
1541
    Label m_false_target;
1542
};
1543
1544
class JumpTrue final : public Instruction {
1545
public:
1546
    constexpr static bool IsTerminator = true;
1547
1548
    explicit JumpTrue(Operand condition, Label target)
1549
0
        : Instruction(Type::JumpTrue)
1550
0
        , m_condition(condition)
1551
0
        , m_target(target)
1552
0
    {
1553
0
    }
1554
1555
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1556
    void visit_labels_impl(Function<void(Label&)> visitor)
1557
0
    {
1558
0
        visitor(m_target);
1559
0
    }
1560
    void visit_operands_impl(Function<void(Operand&)> visitor)
1561
0
    {
1562
0
        visitor(m_condition);
1563
0
    }
1564
1565
0
    Operand condition() const { return m_condition; }
1566
0
    auto& target() const { return m_target; }
1567
1568
private:
1569
    Operand m_condition;
1570
    Label m_target;
1571
};
1572
1573
class JumpFalse final : public Instruction {
1574
public:
1575
    constexpr static bool IsTerminator = true;
1576
1577
    explicit JumpFalse(Operand condition, Label target)
1578
0
        : Instruction(Type::JumpFalse)
1579
0
        , m_condition(condition)
1580
0
        , m_target(target)
1581
0
    {
1582
0
    }
1583
1584
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1585
    void visit_labels_impl(Function<void(Label&)> visitor)
1586
0
    {
1587
0
        visitor(m_target);
1588
0
    }
1589
    void visit_operands_impl(Function<void(Operand&)> visitor)
1590
0
    {
1591
0
        visitor(m_condition);
1592
0
    }
1593
1594
0
    Operand condition() const { return m_condition; }
1595
0
    auto& target() const { return m_target; }
1596
1597
private:
1598
    Operand m_condition;
1599
    Label m_target;
1600
};
1601
1602
#define JS_ENUMERATE_COMPARISON_OPS(X)            \
1603
0
    X(LessThan, less_than, <)                     \
1604
0
    X(LessThanEquals, less_than_equals, <=)       \
1605
0
    X(GreaterThan, greater_than, >)               \
1606
0
    X(GreaterThanEquals, greater_than_equals, >=) \
1607
0
    X(LooselyEquals, loosely_equals, ==)          \
1608
0
    X(LooselyInequals, loosely_inequals, !=)      \
1609
0
    X(StrictlyEquals, strict_equals, ==)          \
1610
0
    X(StrictlyInequals, strict_inequals, !=)
1611
1612
#define DECLARE_COMPARISON_OP(op_TitleCase, op_snake_case, numeric_operator)                         \
1613
    class Jump##op_TitleCase final : public Instruction {                                            \
1614
    public:                                                                                          \
1615
        constexpr static bool IsTerminator = true;                                                   \
1616
                                                                                                     \
1617
        explicit Jump##op_TitleCase(Operand lhs, Operand rhs, Label true_target, Label false_target) \
1618
0
            : Instruction(Type::Jump##op_TitleCase)                                                  \
1619
0
            , m_lhs(lhs)                                                                             \
1620
0
            , m_rhs(rhs)                                                                             \
1621
0
            , m_true_target(true_target)                                                             \
1622
0
            , m_false_target(false_target)                                                           \
1623
0
        {                                                                                            \
1624
0
        }                                                                                            \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::JumpLessThan(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::JumpLessThanEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::JumpGreaterThan(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::JumpGreaterThanEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::JumpLooselyEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::JumpLooselyInequals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::JumpStrictlyEquals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::JumpStrictlyInequals(JS::Bytecode::Operand, JS::Bytecode::Operand, JS::Bytecode::Label, JS::Bytecode::Label)
1625
                                                                                                     \
1626
        ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;                          \
1627
        ByteString to_byte_string_impl(Bytecode::Executable const&) const;                           \
1628
        void visit_labels_impl(Function<void(Label&)> visitor)                                       \
1629
0
        {                                                                                            \
1630
0
            visitor(m_true_target);                                                                  \
1631
0
            visitor(m_false_target);                                                                 \
1632
0
        }                                                                                            \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::visit_labels_impl(AK::Function<void (JS::Bytecode::Label&)>)
1633
        void visit_operands_impl(Function<void(Operand&)> visitor)                                   \
1634
0
        {                                                                                            \
1635
0
            visitor(m_lhs);                                                                          \
1636
0
            visitor(m_rhs);                                                                          \
1637
0
        }                                                                                            \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::visit_operands_impl(AK::Function<void (JS::Bytecode::Operand&)>)
1638
                                                                                                     \
1639
0
        Operand lhs() const { return m_lhs; }                                                        \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::lhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::lhs() const
1640
0
        Operand rhs() const { return m_rhs; }                                                        \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::rhs() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::rhs() const
1641
0
        auto& true_target() const { return m_true_target; }                                          \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::true_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::true_target() const
1642
0
        auto& false_target() const { return m_false_target; }                                        \
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThan::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLessThanEquals::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThan::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpGreaterThanEquals::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyEquals::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpLooselyInequals::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyEquals::false_target() const
Unexecuted instantiation: JS::Bytecode::Op::JumpStrictlyInequals::false_target() const
1643
                                                                                                     \
1644
    private:                                                                                         \
1645
        Operand m_lhs;                                                                               \
1646
        Operand m_rhs;                                                                               \
1647
        Label m_true_target;                                                                         \
1648
        Label m_false_target;                                                                        \
1649
    };
1650
1651
JS_ENUMERATE_COMPARISON_OPS(DECLARE_COMPARISON_OP)
1652
1653
class JumpNullish final : public Instruction {
1654
public:
1655
    constexpr static bool IsTerminator = true;
1656
1657
    explicit JumpNullish(Operand condition, Label true_target, Label false_target)
1658
0
        : Instruction(Type::JumpNullish)
1659
0
        , m_condition(condition)
1660
0
        , m_true_target(true_target)
1661
0
        , m_false_target(false_target)
1662
0
    {
1663
0
    }
1664
1665
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1666
    void visit_labels_impl(Function<void(Label&)> visitor)
1667
0
    {
1668
0
        visitor(m_true_target);
1669
0
        visitor(m_false_target);
1670
0
    }
1671
    void visit_operands_impl(Function<void(Operand&)> visitor)
1672
0
    {
1673
0
        visitor(m_condition);
1674
0
    }
1675
1676
0
    Operand condition() const { return m_condition; }
1677
0
    auto& true_target() const { return m_true_target; }
1678
0
    auto& false_target() const { return m_false_target; }
1679
1680
private:
1681
    Operand m_condition;
1682
    Label m_true_target;
1683
    Label m_false_target;
1684
};
1685
1686
class JumpUndefined final : public Instruction {
1687
public:
1688
    constexpr static bool IsTerminator = true;
1689
1690
    explicit JumpUndefined(Operand condition, Label true_target, Label false_target)
1691
0
        : Instruction(Type::JumpUndefined)
1692
0
        , m_condition(condition)
1693
0
        , m_true_target(true_target)
1694
0
        , m_false_target(false_target)
1695
0
    {
1696
0
    }
1697
1698
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1699
    void visit_labels_impl(Function<void(Label&)> visitor)
1700
0
    {
1701
0
        visitor(m_true_target);
1702
0
        visitor(m_false_target);
1703
0
    }
1704
    void visit_operands_impl(Function<void(Operand&)> visitor)
1705
0
    {
1706
0
        visitor(m_condition);
1707
0
    }
1708
1709
0
    Operand condition() const { return m_condition; }
1710
0
    auto& true_target() const { return m_true_target; }
1711
0
    auto& false_target() const { return m_false_target; }
1712
1713
private:
1714
    Operand m_condition;
1715
    Label m_true_target;
1716
    Label m_false_target;
1717
};
1718
1719
enum class CallType : u8 {
1720
    Call,
1721
    Construct,
1722
    DirectEval,
1723
};
1724
1725
class Call final : public Instruction {
1726
public:
1727
    static constexpr bool IsVariableLength = true;
1728
1729
    Call(CallType type, Operand dst, Operand callee, Operand this_value, ReadonlySpan<ScopedOperand> arguments, Optional<StringTableIndex> expression_string = {}, Optional<Builtin> builtin = {})
1730
0
        : Instruction(Type::Call)
1731
0
        , m_dst(dst)
1732
0
        , m_callee(callee)
1733
0
        , m_this_value(this_value)
1734
0
        , m_argument_count(arguments.size())
1735
0
        , m_type(type)
1736
0
        , m_builtin(builtin)
1737
0
        , m_expression_string(expression_string)
1738
0
    {
1739
0
        for (size_t i = 0; i < arguments.size(); ++i)
1740
0
            m_arguments[i] = arguments[i];
1741
0
    }
1742
1743
    size_t length_impl() const
1744
0
    {
1745
0
        return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Operand) * m_argument_count);
1746
0
    }
1747
1748
0
    CallType call_type() const { return m_type; }
1749
0
    Operand dst() const { return m_dst; }
1750
0
    Operand callee() const { return m_callee; }
1751
0
    Operand this_value() const { return m_this_value; }
1752
0
    Optional<StringTableIndex> const& expression_string() const { return m_expression_string; }
1753
1754
0
    u32 argument_count() const { return m_argument_count; }
1755
1756
0
    Optional<Builtin> const& builtin() const { return m_builtin; }
1757
1758
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1759
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1760
    void visit_operands_impl(Function<void(Operand&)> visitor)
1761
0
    {
1762
0
        visitor(m_dst);
1763
0
        visitor(m_callee);
1764
0
        visitor(m_this_value);
1765
0
        for (size_t i = 0; i < m_argument_count; i++)
1766
0
            visitor(m_arguments[i]);
1767
0
    }
1768
1769
private:
1770
    Operand m_dst;
1771
    Operand m_callee;
1772
    Operand m_this_value;
1773
    u32 m_argument_count { 0 };
1774
    CallType m_type;
1775
    Optional<Builtin> m_builtin;
1776
    Optional<StringTableIndex> m_expression_string;
1777
    Operand m_arguments[];
1778
};
1779
1780
class CallWithArgumentArray final : public Instruction {
1781
public:
1782
    CallWithArgumentArray(CallType type, Operand dst, Operand callee, Operand this_value, Operand arguments, Optional<StringTableIndex> expression_string = {})
1783
0
        : Instruction(Type::CallWithArgumentArray)
1784
0
        , m_dst(dst)
1785
0
        , m_callee(callee)
1786
0
        , m_this_value(this_value)
1787
0
        , m_arguments(arguments)
1788
0
        , m_type(type)
1789
0
        , m_expression_string(expression_string)
1790
0
    {
1791
0
    }
1792
1793
0
    Operand dst() const { return m_dst; }
1794
0
    CallType call_type() const { return m_type; }
1795
0
    Operand callee() const { return m_callee; }
1796
0
    Operand this_value() const { return m_this_value; }
1797
0
    Operand arguments() const { return m_arguments; }
1798
0
    Optional<StringTableIndex> const& expression_string() const { return m_expression_string; }
1799
1800
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1801
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1802
    void visit_operands_impl(Function<void(Operand&)> visitor)
1803
0
    {
1804
0
        visitor(m_dst);
1805
0
        visitor(m_callee);
1806
0
        visitor(m_this_value);
1807
0
        visitor(m_arguments);
1808
0
    }
1809
1810
private:
1811
    Operand m_dst;
1812
    Operand m_callee;
1813
    Operand m_this_value;
1814
    Operand m_arguments;
1815
    CallType m_type;
1816
    Optional<StringTableIndex> m_expression_string;
1817
};
1818
1819
class SuperCallWithArgumentArray : public Instruction {
1820
public:
1821
    explicit SuperCallWithArgumentArray(Operand dst, Operand arguments, bool is_synthetic)
1822
0
        : Instruction(Type::SuperCallWithArgumentArray)
1823
0
        , m_dst(dst)
1824
0
        , m_arguments(arguments)
1825
0
        , m_is_synthetic(is_synthetic)
1826
0
    {
1827
0
    }
1828
1829
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1830
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1831
    void visit_operands_impl(Function<void(Operand&)> visitor)
1832
0
    {
1833
0
        visitor(m_dst);
1834
0
        visitor(m_arguments);
1835
0
    }
1836
1837
0
    Operand dst() const { return m_dst; }
1838
0
    Operand arguments() const { return m_arguments; }
1839
0
    bool is_synthetic() const { return m_is_synthetic; }
1840
1841
private:
1842
    Operand m_dst;
1843
    Operand m_arguments;
1844
    bool m_is_synthetic;
1845
};
1846
1847
class NewClass final : public Instruction {
1848
public:
1849
    static constexpr bool IsVariableLength = true;
1850
1851
    explicit NewClass(Operand dst, Optional<Operand> super_class, ClassExpression const& class_expression, Optional<IdentifierTableIndex> lhs_name, ReadonlySpan<Optional<ScopedOperand>> elements_keys)
1852
0
        : Instruction(Type::NewClass)
1853
0
        , m_dst(dst)
1854
0
        , m_super_class(super_class)
1855
0
        , m_class_expression(class_expression)
1856
0
        , m_lhs_name(lhs_name)
1857
0
        , m_element_keys_count(elements_keys.size())
1858
0
    {
1859
0
        for (size_t i = 0; i < m_element_keys_count; i++) {
1860
0
            if (elements_keys[i].has_value())
1861
0
                m_element_keys[i] = elements_keys[i]->operand();
1862
0
        }
1863
0
    }
1864
1865
    size_t length_impl() const
1866
0
    {
1867
0
        return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Optional<Operand>) * m_element_keys_count);
1868
0
    }
1869
1870
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1871
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1872
    void visit_operands_impl(Function<void(Operand&)> visitor)
1873
0
    {
1874
0
        visitor(m_dst);
1875
0
        if (m_super_class.has_value())
1876
0
            visitor(m_super_class.value());
1877
0
        for (size_t i = 0; i < m_element_keys_count; i++) {
1878
0
            if (m_element_keys[i].has_value())
1879
0
                visitor(m_element_keys[i].value());
1880
0
        }
1881
0
    }
1882
1883
0
    Operand dst() const { return m_dst; }
1884
0
    Optional<Operand> const& super_class() const { return m_super_class; }
1885
0
    ClassExpression const& class_expression() const { return m_class_expression; }
1886
0
    Optional<IdentifierTableIndex> const& lhs_name() const { return m_lhs_name; }
1887
1888
private:
1889
    Operand m_dst;
1890
    Optional<Operand> m_super_class;
1891
    ClassExpression const& m_class_expression;
1892
    Optional<IdentifierTableIndex> m_lhs_name;
1893
    size_t m_element_keys_count { 0 };
1894
    Optional<Operand> m_element_keys[];
1895
};
1896
1897
class NewFunction final : public Instruction {
1898
public:
1899
    explicit NewFunction(Operand dst, FunctionNode const& function_node, Optional<IdentifierTableIndex> lhs_name, Optional<Operand> home_object = {})
1900
0
        : Instruction(Type::NewFunction)
1901
0
        , m_dst(dst)
1902
0
        , m_function_node(function_node)
1903
0
        , m_lhs_name(lhs_name)
1904
0
        , m_home_object(move(home_object))
1905
0
    {
1906
0
    }
1907
1908
    void execute_impl(Bytecode::Interpreter&) const;
1909
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1910
    void visit_operands_impl(Function<void(Operand&)> visitor)
1911
0
    {
1912
0
        visitor(m_dst);
1913
0
        if (m_home_object.has_value())
1914
0
            visitor(m_home_object.value());
1915
0
    }
1916
1917
0
    Operand dst() const { return m_dst; }
1918
0
    FunctionNode const& function_node() const { return m_function_node; }
1919
0
    Optional<IdentifierTableIndex> const& lhs_name() const { return m_lhs_name; }
1920
0
    Optional<Operand> const& home_object() const { return m_home_object; }
1921
1922
private:
1923
    Operand m_dst;
1924
    FunctionNode const& m_function_node;
1925
    Optional<IdentifierTableIndex> m_lhs_name;
1926
    Optional<Operand> m_home_object;
1927
};
1928
1929
class BlockDeclarationInstantiation final : public Instruction {
1930
public:
1931
    explicit BlockDeclarationInstantiation(ScopeNode const& scope_node)
1932
0
        : Instruction(Type::BlockDeclarationInstantiation)
1933
0
        , m_scope_node(scope_node)
1934
0
    {
1935
0
    }
1936
1937
    void execute_impl(Bytecode::Interpreter&) const;
1938
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1939
1940
0
    ScopeNode const& scope_node() const { return m_scope_node; }
1941
1942
private:
1943
    ScopeNode const& m_scope_node;
1944
};
1945
1946
class Return final : public Instruction {
1947
public:
1948
    constexpr static bool IsTerminator = true;
1949
1950
    explicit Return(Optional<Operand> value = {})
1951
0
        : Instruction(Type::Return)
1952
0
        , m_value(value)
1953
0
    {
1954
0
    }
1955
1956
    void execute_impl(Bytecode::Interpreter&) const;
1957
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1958
    void visit_operands_impl(Function<void(Operand&)> visitor)
1959
0
    {
1960
0
        if (m_value.has_value())
1961
0
            visitor(m_value.value());
1962
0
    }
1963
1964
0
    Optional<Operand> const& value() const { return m_value; }
1965
1966
private:
1967
    Optional<Operand> m_value;
1968
};
1969
1970
class Increment final : public Instruction {
1971
public:
1972
    explicit Increment(Operand dst)
1973
0
        : Instruction(Type::Increment)
1974
0
        , m_dst(dst)
1975
0
    {
1976
0
    }
1977
1978
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
1979
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
1980
    void visit_operands_impl(Function<void(Operand&)> visitor)
1981
0
    {
1982
0
        visitor(m_dst);
1983
0
    }
1984
1985
0
    Operand dst() const { return m_dst; }
1986
1987
private:
1988
    Operand m_dst;
1989
};
1990
1991
class PostfixIncrement final : public Instruction {
1992
public:
1993
    explicit PostfixIncrement(Operand dst, Operand src)
1994
0
        : Instruction(Type::PostfixIncrement)
1995
0
        , m_dst(dst)
1996
0
        , m_src(src)
1997
0
    {
1998
0
    }
1999
2000
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2001
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2002
    void visit_operands_impl(Function<void(Operand&)> visitor)
2003
0
    {
2004
0
        visitor(m_dst);
2005
0
        visitor(m_src);
2006
0
    }
2007
2008
0
    Operand dst() const { return m_dst; }
2009
0
    Operand src() const { return m_src; }
2010
2011
private:
2012
    Operand m_dst;
2013
    Operand m_src;
2014
};
2015
2016
class Decrement final : public Instruction {
2017
public:
2018
    explicit Decrement(Operand dst)
2019
0
        : Instruction(Type::Decrement)
2020
0
        , m_dst(dst)
2021
0
    {
2022
0
    }
2023
2024
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2025
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2026
    void visit_operands_impl(Function<void(Operand&)> visitor)
2027
0
    {
2028
0
        visitor(m_dst);
2029
0
    }
2030
2031
0
    Operand dst() const { return m_dst; }
2032
2033
private:
2034
    Operand m_dst;
2035
};
2036
2037
class PostfixDecrement final : public Instruction {
2038
public:
2039
    explicit PostfixDecrement(Operand dst, Operand src)
2040
0
        : Instruction(Type::PostfixDecrement)
2041
0
        , m_dst(dst)
2042
0
        , m_src(src)
2043
0
    {
2044
0
    }
2045
2046
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2047
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2048
    void visit_operands_impl(Function<void(Operand&)> visitor)
2049
0
    {
2050
0
        visitor(m_dst);
2051
0
        visitor(m_src);
2052
0
    }
2053
2054
0
    Operand dst() const { return m_dst; }
2055
0
    Operand src() const { return m_src; }
2056
2057
private:
2058
    Operand m_dst;
2059
    Operand m_src;
2060
};
2061
2062
class Throw final : public Instruction {
2063
public:
2064
    constexpr static bool IsTerminator = true;
2065
2066
    explicit Throw(Operand src)
2067
0
        : Instruction(Type::Throw)
2068
0
        , m_src(src)
2069
0
    {
2070
0
    }
2071
2072
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2073
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2074
    void visit_operands_impl(Function<void(Operand&)> visitor)
2075
0
    {
2076
0
        visitor(m_src);
2077
0
    }
2078
2079
0
    Operand src() const { return m_src; }
2080
2081
private:
2082
    Operand m_src;
2083
};
2084
2085
class ThrowIfNotObject final : public Instruction {
2086
public:
2087
    ThrowIfNotObject(Operand src)
2088
0
        : Instruction(Type::ThrowIfNotObject)
2089
0
        , m_src(src)
2090
0
    {
2091
0
    }
2092
2093
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2094
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2095
    void visit_operands_impl(Function<void(Operand&)> visitor)
2096
0
    {
2097
0
        visitor(m_src);
2098
0
    }
2099
2100
0
    Operand src() const { return m_src; }
2101
2102
private:
2103
    Operand m_src;
2104
};
2105
2106
class ThrowIfNullish final : public Instruction {
2107
public:
2108
    explicit ThrowIfNullish(Operand src)
2109
0
        : Instruction(Type::ThrowIfNullish)
2110
0
        , m_src(src)
2111
0
    {
2112
0
    }
2113
2114
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2115
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2116
    void visit_operands_impl(Function<void(Operand&)> visitor)
2117
0
    {
2118
0
        visitor(m_src);
2119
0
    }
2120
2121
0
    Operand src() const { return m_src; }
2122
2123
private:
2124
    Operand m_src;
2125
};
2126
2127
class ThrowIfTDZ final : public Instruction {
2128
public:
2129
    explicit ThrowIfTDZ(Operand src)
2130
0
        : Instruction(Type::ThrowIfTDZ)
2131
0
        , m_src(src)
2132
0
    {
2133
0
    }
2134
2135
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2136
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2137
    void visit_operands_impl(Function<void(Operand&)> visitor)
2138
0
    {
2139
0
        visitor(m_src);
2140
0
    }
2141
2142
0
    Operand src() const { return m_src; }
2143
2144
private:
2145
    Operand m_src;
2146
};
2147
2148
class EnterUnwindContext final : public Instruction {
2149
public:
2150
    constexpr static bool IsTerminator = true;
2151
2152
    EnterUnwindContext(Label entry_point)
2153
0
        : Instruction(Type::EnterUnwindContext)
2154
0
        , m_entry_point(move(entry_point))
2155
0
    {
2156
0
    }
2157
2158
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2159
    void visit_labels_impl(Function<void(Label&)> visitor)
2160
0
    {
2161
0
        visitor(m_entry_point);
2162
0
    }
2163
2164
0
    auto& entry_point() const { return m_entry_point; }
2165
2166
private:
2167
    Label m_entry_point;
2168
};
2169
2170
class ScheduleJump final : public Instruction {
2171
public:
2172
    // Note: We use this instruction to tell the next `finally` block to
2173
    //       continue execution with a specific break/continue target;
2174
    constexpr static bool IsTerminator = true;
2175
2176
    ScheduleJump(Label target)
2177
0
        : Instruction(Type::ScheduleJump)
2178
0
        , m_target(target)
2179
0
    {
2180
0
    }
2181
2182
0
    Label target() const { return m_target; }
2183
2184
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2185
    void visit_labels_impl(Function<void(Label&)> visitor)
2186
0
    {
2187
0
        visitor(m_target);
2188
0
    }
2189
2190
private:
2191
    Label m_target;
2192
};
2193
2194
class LeaveLexicalEnvironment final : public Instruction {
2195
public:
2196
    LeaveLexicalEnvironment()
2197
0
        : Instruction(Type::LeaveLexicalEnvironment)
2198
0
    {
2199
0
    }
2200
2201
    void execute_impl(Bytecode::Interpreter&) const;
2202
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2203
};
2204
2205
class LeavePrivateEnvironment final : public Instruction {
2206
public:
2207
    LeavePrivateEnvironment()
2208
0
        : Instruction(Type::LeavePrivateEnvironment)
2209
0
    {
2210
0
    }
2211
2212
    void execute_impl(Bytecode::Interpreter&) const;
2213
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2214
};
2215
2216
class LeaveUnwindContext final : public Instruction {
2217
public:
2218
    LeaveUnwindContext()
2219
0
        : Instruction(Type::LeaveUnwindContext)
2220
0
    {
2221
0
    }
2222
2223
    void execute_impl(Bytecode::Interpreter&) const;
2224
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2225
};
2226
2227
class ContinuePendingUnwind final : public Instruction {
2228
public:
2229
    constexpr static bool IsTerminator = true;
2230
2231
    explicit ContinuePendingUnwind(Label resume_target)
2232
0
        : Instruction(Type::ContinuePendingUnwind)
2233
0
        , m_resume_target(resume_target)
2234
0
    {
2235
0
    }
2236
2237
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2238
    void visit_labels_impl(Function<void(Label&)> visitor)
2239
0
    {
2240
0
        visitor(m_resume_target);
2241
0
    }
2242
2243
0
    auto& resume_target() const { return m_resume_target; }
2244
2245
private:
2246
    Label m_resume_target;
2247
};
2248
2249
class Yield final : public Instruction {
2250
public:
2251
    constexpr static bool IsTerminator = true;
2252
2253
    explicit Yield(Label continuation_label, Operand value)
2254
0
        : Instruction(Type::Yield)
2255
0
        , m_continuation_label(continuation_label)
2256
0
        , m_value(value)
2257
0
    {
2258
0
    }
2259
2260
    explicit Yield(nullptr_t, Operand value)
2261
0
        : Instruction(Type::Yield)
2262
0
        , m_value(value)
2263
0
    {
2264
0
    }
2265
2266
    void execute_impl(Bytecode::Interpreter&) const;
2267
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2268
    void visit_labels_impl(Function<void(Label&)> visitor)
2269
0
    {
2270
0
        if (m_continuation_label.has_value())
2271
0
            visitor(m_continuation_label.value());
2272
0
    }
2273
    void visit_operands_impl(Function<void(Operand&)> visitor)
2274
0
    {
2275
0
        visitor(m_value);
2276
0
    }
2277
2278
0
    auto& continuation() const { return m_continuation_label; }
2279
0
    Operand value() const { return m_value; }
2280
2281
private:
2282
    Optional<Label> m_continuation_label;
2283
    Operand m_value;
2284
};
2285
2286
class PrepareYield final : public Instruction {
2287
public:
2288
    explicit PrepareYield(Operand dest, Operand value)
2289
0
        : Instruction(Type::PrepareYield)
2290
0
        , m_dest(dest)
2291
0
        , m_value(value)
2292
0
    {
2293
0
    }
2294
2295
    void execute_impl(Bytecode::Interpreter&) const;
2296
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2297
    void visit_operands_impl(Function<void(Operand&)> visitor)
2298
0
    {
2299
0
        visitor(m_dest);
2300
0
        visitor(m_value);
2301
0
    }
2302
2303
0
    Operand destination() const { return m_dest; }
2304
0
    Operand value() const { return m_value; }
2305
2306
private:
2307
    Operand m_dest;
2308
    Operand m_value;
2309
};
2310
2311
class Await final : public Instruction {
2312
public:
2313
    constexpr static bool IsTerminator = true;
2314
2315
    explicit Await(Label continuation_label, Operand argument)
2316
0
        : Instruction(Type::Await)
2317
0
        , m_continuation_label(continuation_label)
2318
0
        , m_argument(argument)
2319
0
    {
2320
0
    }
2321
2322
    void execute_impl(Bytecode::Interpreter&) const;
2323
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2324
    void visit_labels_impl(Function<void(Label&)> visitor)
2325
0
    {
2326
0
        visitor(m_continuation_label);
2327
0
    }
2328
    void visit_operands_impl(Function<void(Operand&)> visitor)
2329
0
    {
2330
0
        visitor(m_argument);
2331
0
    }
2332
2333
0
    auto& continuation() const { return m_continuation_label; }
2334
0
    Operand argument() const { return m_argument; }
2335
2336
private:
2337
    Label m_continuation_label;
2338
    Operand m_argument;
2339
};
2340
2341
class GetIterator final : public Instruction {
2342
public:
2343
    GetIterator(Operand dst, Operand iterable, IteratorHint hint = IteratorHint::Sync)
2344
0
        : Instruction(Type::GetIterator)
2345
0
        , m_dst(dst)
2346
0
        , m_iterable(iterable)
2347
0
        , m_hint(hint)
2348
0
    {
2349
0
    }
2350
2351
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2352
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2353
    void visit_operands_impl(Function<void(Operand&)> visitor)
2354
0
    {
2355
0
        visitor(m_dst);
2356
0
        visitor(m_iterable);
2357
0
    }
2358
2359
0
    Operand dst() const { return m_dst; }
2360
0
    Operand iterable() const { return m_iterable; }
2361
0
    IteratorHint hint() const { return m_hint; }
2362
2363
private:
2364
    Operand m_dst;
2365
    Operand m_iterable;
2366
    IteratorHint m_hint { IteratorHint::Sync };
2367
};
2368
2369
class GetObjectFromIteratorRecord final : public Instruction {
2370
public:
2371
    GetObjectFromIteratorRecord(Operand object, Operand iterator_record)
2372
0
        : Instruction(Type::GetObjectFromIteratorRecord)
2373
0
        , m_object(object)
2374
0
        , m_iterator_record(iterator_record)
2375
0
    {
2376
0
    }
2377
2378
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2379
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2380
    void visit_operands_impl(Function<void(Operand&)> visitor)
2381
0
    {
2382
0
        visitor(m_object);
2383
0
        visitor(m_iterator_record);
2384
0
    }
2385
2386
0
    Operand object() const { return m_object; }
2387
0
    Operand iterator_record() const { return m_iterator_record; }
2388
2389
private:
2390
    Operand m_object;
2391
    Operand m_iterator_record;
2392
};
2393
2394
class GetNextMethodFromIteratorRecord final : public Instruction {
2395
public:
2396
    GetNextMethodFromIteratorRecord(Operand next_method, Operand iterator_record)
2397
0
        : Instruction(Type::GetNextMethodFromIteratorRecord)
2398
0
        , m_next_method(next_method)
2399
0
        , m_iterator_record(iterator_record)
2400
0
    {
2401
0
    }
2402
2403
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2404
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2405
    void visit_operands_impl(Function<void(Operand&)> visitor)
2406
0
    {
2407
0
        visitor(m_next_method);
2408
0
        visitor(m_iterator_record);
2409
0
    }
2410
2411
0
    Operand next_method() const { return m_next_method; }
2412
0
    Operand iterator_record() const { return m_iterator_record; }
2413
2414
private:
2415
    Operand m_next_method;
2416
    Operand m_iterator_record;
2417
};
2418
2419
class GetMethod final : public Instruction {
2420
public:
2421
    GetMethod(Operand dst, Operand object, IdentifierTableIndex property)
2422
0
        : Instruction(Type::GetMethod)
2423
0
        , m_dst(dst)
2424
0
        , m_object(object)
2425
0
        , m_property(property)
2426
0
    {
2427
0
    }
2428
2429
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2430
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2431
    void visit_operands_impl(Function<void(Operand&)> visitor)
2432
0
    {
2433
0
        visitor(m_dst);
2434
0
        visitor(m_object);
2435
0
    }
2436
2437
0
    Operand dst() const { return m_dst; }
2438
0
    Operand object() const { return m_object; }
2439
0
    IdentifierTableIndex property() const { return m_property; }
2440
2441
private:
2442
    Operand m_dst;
2443
    Operand m_object;
2444
    IdentifierTableIndex m_property;
2445
};
2446
2447
class GetObjectPropertyIterator final : public Instruction {
2448
public:
2449
    GetObjectPropertyIterator(Operand dst, Operand object)
2450
0
        : Instruction(Type::GetObjectPropertyIterator)
2451
0
        , m_dst(dst)
2452
0
        , m_object(object)
2453
0
    {
2454
0
    }
2455
2456
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2457
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2458
    void visit_operands_impl(Function<void(Operand&)> visitor)
2459
0
    {
2460
0
        visitor(m_dst);
2461
0
        visitor(m_object);
2462
0
    }
2463
2464
0
    Operand dst() const { return m_dst; }
2465
0
    Operand object() const { return m_object; }
2466
2467
private:
2468
    Operand m_dst;
2469
    Operand m_object;
2470
};
2471
2472
class IteratorClose final : public Instruction {
2473
public:
2474
    IteratorClose(Operand iterator_record, Completion::Type completion_type, Optional<Value> completion_value)
2475
0
        : Instruction(Type::IteratorClose)
2476
0
        , m_iterator_record(iterator_record)
2477
0
        , m_completion_type(completion_type)
2478
0
        , m_completion_value(completion_value)
2479
0
    {
2480
0
    }
2481
2482
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2483
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2484
    void visit_operands_impl(Function<void(Operand&)> visitor)
2485
0
    {
2486
0
        visitor(m_iterator_record);
2487
0
    }
2488
2489
0
    Operand iterator_record() const { return m_iterator_record; }
2490
0
    Completion::Type completion_type() const { return m_completion_type; }
2491
0
    Optional<Value> const& completion_value() const { return m_completion_value; }
2492
2493
private:
2494
    Operand m_iterator_record;
2495
    Completion::Type m_completion_type { Completion::Type::Normal };
2496
    Optional<Value> m_completion_value;
2497
};
2498
2499
class AsyncIteratorClose final : public Instruction {
2500
public:
2501
    AsyncIteratorClose(Operand iterator_record, Completion::Type completion_type, Optional<Value> completion_value)
2502
0
        : Instruction(Type::AsyncIteratorClose)
2503
0
        , m_iterator_record(iterator_record)
2504
0
        , m_completion_type(completion_type)
2505
0
        , m_completion_value(completion_value)
2506
0
    {
2507
0
    }
2508
2509
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2510
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2511
    void visit_operands_impl(Function<void(Operand&)> visitor)
2512
0
    {
2513
0
        visitor(m_iterator_record);
2514
0
    }
2515
2516
0
    Operand iterator_record() const { return m_iterator_record; }
2517
0
    Completion::Type completion_type() const { return m_completion_type; }
2518
0
    Optional<Value> const& completion_value() const { return m_completion_value; }
2519
2520
private:
2521
    Operand m_iterator_record;
2522
    Completion::Type m_completion_type { Completion::Type::Normal };
2523
    Optional<Value> m_completion_value;
2524
};
2525
2526
class IteratorNext final : public Instruction {
2527
public:
2528
    IteratorNext(Operand dst, Operand iterator_record)
2529
0
        : Instruction(Type::IteratorNext)
2530
0
        , m_dst(dst)
2531
0
        , m_iterator_record(iterator_record)
2532
0
    {
2533
0
    }
2534
2535
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2536
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2537
    void visit_operands_impl(Function<void(Operand&)> visitor)
2538
0
    {
2539
0
        visitor(m_dst);
2540
0
        visitor(m_iterator_record);
2541
0
    }
2542
2543
0
    Operand dst() const { return m_dst; }
2544
0
    Operand iterator_record() const { return m_iterator_record; }
2545
2546
private:
2547
    Operand m_dst;
2548
    Operand m_iterator_record;
2549
};
2550
2551
class ResolveThisBinding final : public Instruction {
2552
public:
2553
    ResolveThisBinding()
2554
0
        : Instruction(Type::ResolveThisBinding)
2555
0
    {
2556
0
    }
2557
2558
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2559
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2560
0
    void visit_operands_impl(Function<void(Operand&)>) { }
2561
};
2562
2563
class ResolveSuperBase final : public Instruction {
2564
public:
2565
    explicit ResolveSuperBase(Operand dst)
2566
0
        : Instruction(Type::ResolveSuperBase)
2567
0
        , m_dst(dst)
2568
0
    {
2569
0
    }
2570
2571
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2572
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2573
    void visit_operands_impl(Function<void(Operand&)> visitor)
2574
0
    {
2575
0
        visitor(m_dst);
2576
0
    }
2577
2578
0
    Operand dst() const { return m_dst; }
2579
2580
private:
2581
    Operand m_dst;
2582
};
2583
2584
class GetNewTarget final : public Instruction {
2585
public:
2586
    explicit GetNewTarget(Operand dst)
2587
0
        : Instruction(Type::GetNewTarget)
2588
0
        , m_dst(dst)
2589
0
    {
2590
0
    }
2591
2592
    void execute_impl(Bytecode::Interpreter&) const;
2593
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2594
    void visit_operands_impl(Function<void(Operand&)> visitor)
2595
0
    {
2596
0
        visitor(m_dst);
2597
0
    }
2598
2599
0
    Operand dst() const { return m_dst; }
2600
2601
private:
2602
    Operand m_dst;
2603
};
2604
2605
class GetImportMeta final : public Instruction {
2606
public:
2607
    explicit GetImportMeta(Operand dst)
2608
0
        : Instruction(Type::GetImportMeta)
2609
0
        , m_dst(dst)
2610
0
    {
2611
0
    }
2612
2613
    void execute_impl(Bytecode::Interpreter&) const;
2614
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2615
    void visit_operands_impl(Function<void(Operand&)> visitor)
2616
0
    {
2617
0
        visitor(m_dst);
2618
0
    }
2619
2620
0
    Operand dst() const { return m_dst; }
2621
2622
private:
2623
    Operand m_dst;
2624
};
2625
2626
class TypeofBinding final : public Instruction {
2627
public:
2628
    TypeofBinding(Operand dst, IdentifierTableIndex identifier)
2629
0
        : Instruction(Type::TypeofBinding)
2630
0
        , m_dst(dst)
2631
0
        , m_identifier(identifier)
2632
0
    {
2633
0
    }
2634
2635
    ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
2636
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2637
    void visit_operands_impl(Function<void(Operand&)> visitor)
2638
0
    {
2639
0
        visitor(m_dst);
2640
0
    }
2641
2642
0
    Operand dst() const { return m_dst; }
2643
0
    IdentifierTableIndex identifier() const { return m_identifier; }
2644
2645
private:
2646
    Operand m_dst;
2647
    IdentifierTableIndex m_identifier;
2648
    mutable EnvironmentCoordinate m_cache;
2649
};
2650
2651
class End final : public Instruction {
2652
public:
2653
    constexpr static bool IsTerminator = true;
2654
2655
    explicit End(Operand value)
2656
24
        : Instruction(Type::End)
2657
24
        , m_value(value)
2658
24
    {
2659
24
    }
2660
2661
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2662
    void visit_operands_impl(Function<void(Operand&)> visitor)
2663
24
    {
2664
24
        visitor(m_value);
2665
24
    }
2666
2667
15
    Operand value() const { return m_value; }
2668
2669
private:
2670
    Operand m_value;
2671
};
2672
2673
class Dump final : public Instruction {
2674
public:
2675
    explicit Dump(StringView text, Operand value)
2676
        : Instruction(Type::Dump)
2677
        , m_text(text)
2678
        , m_value(value)
2679
0
    {
2680
0
    }
2681
2682
    void execute_impl(Bytecode::Interpreter&) const;
2683
    ByteString to_byte_string_impl(Bytecode::Executable const&) const;
2684
    void visit_operands_impl(Function<void(Operand&)> visitor)
2685
0
    {
2686
0
        visitor(m_value);
2687
0
    }
2688
2689
private:
2690
    StringView m_text;
2691
    Operand m_value;
2692
};
2693
2694
}