summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Bytecode/Instruction.h
blob: 72255f2412cb609ac5c7a277da3ef74d767614d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Forward.h>
#include <AK/Span.h>
#include <LibJS/Forward.h>

#define ENUMERATE_BYTECODE_OPS(O)    \
    O(Add)                           \
    O(Append)                        \
    O(BitwiseAnd)                    \
    O(BitwiseNot)                    \
    O(BitwiseOr)                     \
    O(BitwiseXor)                    \
    O(Call)                          \
    O(ConcatString)                  \
    O(ContinuePendingUnwind)         \
    O(CopyObjectExcludingProperties) \
    O(CreateEnvironment)             \
    O(CreateVariable)                \
    O(Decrement)                     \
    O(DeleteById)                    \
    O(DeleteByValue)                 \
    O(DeleteVariable)                \
    O(Div)                           \
    O(EnterUnwindContext)            \
    O(EnterObjectEnvironment)        \
    O(Exp)                           \
    O(GetById)                       \
    O(GetByValue)                    \
    O(GetIterator)                   \
    O(GetMethod)                     \
    O(GetNewTarget)                  \
    O(GetObjectPropertyIterator)     \
    O(GetVariable)                   \
    O(GreaterThan)                   \
    O(GreaterThanEquals)             \
    O(In)                            \
    O(Increment)                     \
    O(InstanceOf)                    \
    O(IteratorClose)                 \
    O(IteratorNext)                  \
    O(IteratorResultDone)            \
    O(IteratorResultValue)           \
    O(IteratorToArray)               \
    O(Jump)                          \
    O(JumpConditional)               \
    O(JumpNullish)                   \
    O(JumpUndefined)                 \
    O(LeaveEnvironment)              \
    O(LeaveUnwindContext)            \
    O(LeftShift)                     \
    O(LessThan)                      \
    O(LessThanEquals)                \
    O(Load)                          \
    O(LoadImmediate)                 \
    O(LooselyEquals)                 \
    O(LooselyInequals)               \
    O(Mod)                           \
    O(Mul)                           \
    O(NewArray)                      \
    O(NewBigInt)                     \
    O(NewClass)                      \
    O(NewFunction)                   \
    O(NewObject)                     \
    O(NewRegExp)                     \
    O(NewString)                     \
    O(NewTypeError)                  \
    O(Not)                           \
    O(PushDeclarativeEnvironment)    \
    O(PutById)                       \
    O(PutByValue)                    \
    O(ResolveThisBinding)            \
    O(Return)                        \
    O(RightShift)                    \
    O(SetVariable)                   \
    O(Store)                         \
    O(StrictlyEquals)                \
    O(StrictlyInequals)              \
    O(Sub)                           \
    O(SuperCall)                     \
    O(Throw)                         \
    O(ThrowIfNotObject)              \
    O(Typeof)                        \
    O(TypeofVariable)                \
    O(UnaryMinus)                    \
    O(UnaryPlus)                     \
    O(UnsignedRightShift)            \
    O(Yield)

namespace JS::Bytecode {

class alignas(void*) Instruction {
public:
    constexpr static bool IsTerminator = false;

    enum class Type {
#define __BYTECODE_OP(op) \
    op,
        ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
#undef __BYTECODE_OP
    };

    bool is_terminator() const;
    Type type() const { return m_type; }
    size_t length() const;
    DeprecatedString to_deprecated_string(Bytecode::Executable const&) const;
    ThrowCompletionOr<void> execute(Bytecode::Interpreter&) const;
    void replace_references(BasicBlock const&, BasicBlock const&);
    void replace_references(Register, Register);
    static void destroy(Instruction&);

protected:
    explicit Instruction(Type type)
        : m_type(type)
    {
    }

private:
    Type m_type {};
};

class InstructionStreamIterator {
public:
    explicit InstructionStreamIterator(ReadonlyBytes bytes)
        : m_bytes(bytes)
    {
    }

    size_t offset() const { return m_offset; }
    bool at_end() const { return m_offset >= m_bytes.size(); }
    void jump(size_t offset)
    {
        VERIFY(offset <= m_bytes.size());
        m_offset = offset;
    }

    Instruction const& operator*() const { return dereference(); }

    ALWAYS_INLINE void operator++()
    {
        VERIFY(!at_end());
        m_offset += dereference().length();
    }

private:
    Instruction const& dereference() const { return *reinterpret_cast<Instruction const*>(m_bytes.data() + offset()); }

    ReadonlyBytes m_bytes;
    size_t m_offset { 0 };
};

}