blob: b38ed0b804f1a585a3883ddcea8e4cfb04fb69db (
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
|
/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Forward.h>
#include <LibJS/Bytecode/Block.h>
#include <LibJS/Forward.h>
#define ENUMERATE_BYTECODE_OPS(O) \
O(Load) \
O(LoadImmediate) \
O(Store) \
O(Add) \
O(Sub) \
O(Mul) \
O(Div) \
O(Mod) \
O(Exp) \
O(GreaterThan) \
O(GreaterThanEquals) \
O(LessThan) \
O(LessThanEquals) \
O(AbstractInequals) \
O(AbstractEquals) \
O(TypedInequals) \
O(TypedEquals) \
O(NewBigInt) \
O(NewString) \
O(NewObject) \
O(GetVariable) \
O(SetVariable) \
O(PutById) \
O(GetById) \
O(Jump) \
O(JumpIfFalse) \
O(JumpIfTrue) \
O(JumpIfNotNullish) \
O(Call) \
O(EnterScope) \
O(Return) \
O(BitwiseAnd) \
O(BitwiseOr) \
O(BitwiseXor) \
O(BitwiseNot) \
O(Not) \
O(UnaryPlus) \
O(UnaryMinus) \
O(Typeof) \
O(LeftShift) \
O(RightShift) \
O(UnsignedRightShift) \
O(In) \
O(InstanceOf) \
O(ConcatString)
namespace JS::Bytecode {
class Instruction {
public:
enum class Type {
#define __BYTECODE_OP(op) \
op,
ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
#undef __BYTECODE_OP
};
Type type() const { return m_type; }
size_t length() const;
String to_string() const;
void execute(Bytecode::Interpreter&) const;
static void destroy(Instruction&);
protected:
explicit Instruction(Type type)
: m_type(type)
{
}
private:
Type m_type {};
};
template<typename OpType>
class InstructionHandle {
public:
InstructionHandle() = default;
InstructionHandle(size_t offset, Block* block)
: m_offset(offset)
, m_block(block)
{
}
OpType* operator->() const
{
VERIFY(m_block);
return reinterpret_cast<OpType*>(m_block->buffer().data() + m_offset);
}
OpType& operator*() const
{
VERIFY(m_block);
return *reinterpret_cast<OpType*>(m_block->buffer().data() + m_offset);
}
template<typename T>
InstructionHandle<OpType>& operator=(InstructionHandle<T> const& other) requires(IsBaseOf<OpType, T>)
{
m_offset = other.offset();
m_block = other.block();
return *this;
}
size_t offset() const { return m_offset; }
Block* block() const { return m_block; }
private:
friend class Block;
size_t m_offset { 0 };
Block* m_block { nullptr };
};
}
|