| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-06-07 21:13:37 +01:00
										 |  |  |  * Copyright (c) 2021, Linus Groh <linusg@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-06-09 18:18:56 +02:00
										 |  |  |  * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 07:59:25 +02:00
										 |  |  | #include <LibCrypto/BigInt/SignedBigInteger.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | #include <LibJS/Bytecode/Instruction.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  | #include <LibJS/Bytecode/Label.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | #include <LibJS/Bytecode/Register.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  | #include <LibJS/Bytecode/StringTable.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | #include <LibJS/Heap/Cell.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-10 22:12:21 +02:00
										 |  |  | #include <LibJS/Runtime/ScopeObject.h>
 | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | #include <LibJS/Runtime/Value.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace JS::Bytecode::Op { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Load final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |     Load(Register src) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::Load) | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |         , m_src(src) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Register m_src; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class LoadImmediate final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     LoadImmediate(Value value) | 
					
						
							|  |  |  |         : Instruction(Type::LoadImmediate) | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  |         , m_value(value) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Value m_value; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  | class Store final : public Instruction { | 
					
						
							| 
									
										
										
										
											2021-06-07 22:05:09 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |     Store(Register dst) | 
					
						
							|  |  |  |         : Instruction(Type::Store) | 
					
						
							| 
									
										
										
										
											2021-06-07 22:05:09 +02:00
										 |  |  |         , m_dst(dst) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-07 22:05:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Register m_dst; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  | #define JS_ENUMERATE_COMMON_BINARY_OPS(O)     \
 | 
					
						
							|  |  |  |     O(Add, add)                               \ | 
					
						
							|  |  |  |     O(Sub, sub)                               \ | 
					
						
							|  |  |  |     O(Mul, mul)                               \ | 
					
						
							|  |  |  |     O(Div, div)                               \ | 
					
						
							|  |  |  |     O(Exp, exp)                               \ | 
					
						
							|  |  |  |     O(Mod, mod)                               \ | 
					
						
							|  |  |  |     O(In, in)                                 \ | 
					
						
							|  |  |  |     O(InstanceOf, instance_of)                \ | 
					
						
							|  |  |  |     O(GreaterThan, greater_than)              \ | 
					
						
							|  |  |  |     O(GreaterThanEquals, greater_than_equals) \ | 
					
						
							|  |  |  |     O(LessThan, less_than)                    \ | 
					
						
							|  |  |  |     O(LessThanEquals, less_than_equals)       \ | 
					
						
							|  |  |  |     O(AbstractInequals, abstract_inequals)    \ | 
					
						
							|  |  |  |     O(AbstractEquals, abstract_equals)        \ | 
					
						
							|  |  |  |     O(TypedInequals, typed_inequals)          \ | 
					
						
							|  |  |  |     O(TypedEquals, typed_equals)              \ | 
					
						
							|  |  |  |     O(BitwiseAnd, bitwise_and)                \ | 
					
						
							|  |  |  |     O(BitwiseOr, bitwise_or)                  \ | 
					
						
							|  |  |  |     O(BitwiseXor, bitwise_xor)                \ | 
					
						
							|  |  |  |     O(LeftShift, left_shift)                  \ | 
					
						
							|  |  |  |     O(RightShift, right_shift)                \ | 
					
						
							|  |  |  |     O(UnsignedRightShift, unsigned_right_shift) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
 | 
					
						
							|  |  |  |     class OpTitleCase final : public Instruction {              \ | 
					
						
							|  |  |  |     public:                                                     \ | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |         OpTitleCase(Register lhs_reg)                           \ | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  |             : Instruction(Type::OpTitleCase)                    \ | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |             , m_lhs_reg(lhs_reg)                                \ | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  |         {                                                       \ | 
					
						
							|  |  |  |         }                                                       \ | 
					
						
							|  |  |  |                                                                 \ | 
					
						
							|  |  |  |         void execute(Bytecode::Interpreter&) const;             \ | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |         String to_string(Bytecode::Executable const&) const;    \ | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  |                                                                 \ | 
					
						
							|  |  |  |     private:                                                    \ | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |         Register m_lhs_reg;                                     \ | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP) | 
					
						
							|  |  |  | #undef JS_DECLARE_COMMON_BINARY_OP
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
 | 
					
						
							|  |  |  |     O(BitwiseNot, bitwise_not)           \ | 
					
						
							|  |  |  |     O(Not, not_)                         \ | 
					
						
							|  |  |  |     O(UnaryPlus, unary_plus)             \ | 
					
						
							|  |  |  |     O(UnaryMinus, unary_minus)           \ | 
					
						
							|  |  |  |     O(Typeof, typeof_) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
 | 
					
						
							|  |  |  |     class OpTitleCase final : public Instruction {             \ | 
					
						
							|  |  |  |     public:                                                    \ | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |         OpTitleCase()                                          \ | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  |             : Instruction(Type::OpTitleCase)                   \ | 
					
						
							|  |  |  |         {                                                      \ | 
					
						
							|  |  |  |         }                                                      \ | 
					
						
							|  |  |  |                                                                \ | 
					
						
							|  |  |  |         void execute(Bytecode::Interpreter&) const;            \ | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |         String to_string(Bytecode::Executable const&) const;   \ | 
					
						
							| 
									
										
										
										
											2021-06-07 23:08:35 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP) | 
					
						
							|  |  |  | #undef JS_DECLARE_COMMON_UNARY_OP
 | 
					
						
							| 
									
										
										
										
											2021-06-07 19:53:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | class NewString final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     NewString(StringTableIndex string) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::NewString) | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  |         , m_string(move(string)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     StringTableIndex m_string; | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 20:30:23 +02:00
										 |  |  | class NewObject final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |     NewObject() | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::NewObject) | 
					
						
							| 
									
										
										
										
											2021-06-04 20:30:23 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-04 20:30:23 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 07:59:25 +02:00
										 |  |  | class NewBigInt final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |     explicit NewBigInt(Crypto::SignedBigInteger bigint) | 
					
						
							| 
									
										
										
										
											2021-06-08 07:59:25 +02:00
										 |  |  |         : Instruction(Type::NewBigInt) | 
					
						
							|  |  |  |         , m_bigint(move(bigint)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-08 07:59:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Crypto::SignedBigInteger m_bigint; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 23:06:52 +02:00
										 |  |  | // NOTE: This instruction is variable-width depending on the number of elements!
 | 
					
						
							|  |  |  | class NewArray final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     NewArray(Vector<Register> const& elements) | 
					
						
							|  |  |  |         : Instruction(Type::NewArray) | 
					
						
							|  |  |  |         , m_element_count(elements.size()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         for (size_t i = 0; i < m_element_count; ++i) | 
					
						
							|  |  |  |             m_elements[i] = elements[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-08 23:06:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     size_t m_element_count { 0 }; | 
					
						
							|  |  |  |     Register m_elements[]; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  | class ConcatString final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     ConcatString(Register lhs) | 
					
						
							|  |  |  |         : Instruction(Type::ConcatString) | 
					
						
							|  |  |  |         , m_lhs(lhs) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Register m_lhs; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | class SetVariable final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     SetVariable(StringTableIndex identifier) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::SetVariable) | 
					
						
							|  |  |  |         , m_identifier(move(identifier)) | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     StringTableIndex m_identifier; | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class GetVariable final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     GetVariable(StringTableIndex identifier) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::GetVariable) | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  |         , m_identifier(move(identifier)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     StringTableIndex m_identifier; | 
					
						
							| 
									
										
										
										
											2021-06-03 18:26:32 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 21:03:53 +02:00
										 |  |  | class GetById final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     GetById(StringTableIndex property) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::GetById) | 
					
						
							| 
									
										
										
										
											2021-06-04 21:03:53 +02:00
										 |  |  |         , m_property(move(property)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-04 21:03:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     StringTableIndex m_property; | 
					
						
							| 
									
										
										
										
											2021-06-04 21:03:53 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 20:47:07 +02:00
										 |  |  | class PutById final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     PutById(Register base, StringTableIndex property) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::PutById) | 
					
						
							|  |  |  |         , m_base(base) | 
					
						
							| 
									
										
										
										
											2021-06-04 20:47:07 +02:00
										 |  |  |         , m_property(move(property)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-04 20:47:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Register m_base; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     StringTableIndex m_property; | 
					
						
							| 
									
										
										
										
											2021-06-04 20:47:07 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 11:28:27 +02:00
										 |  |  | class Jump : public Instruction { | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |     constexpr static bool IsTerminator = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {}) | 
					
						
							| 
									
										
										
										
											2021-06-08 11:28:27 +02:00
										 |  |  |         : Instruction(type) | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |         , m_true_target(move(taken_target)) | 
					
						
							|  |  |  |         , m_false_target(move(nontaken_target)) | 
					
						
							| 
									
										
										
										
											2021-06-08 11:28:27 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |     explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {}) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::Jump) | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |         , m_true_target(move(taken_target)) | 
					
						
							|  |  |  |         , m_false_target(move(nontaken_target)) | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |     void set_targets(Optional<Label> true_target, Optional<Label> false_target) | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |         m_true_target = move(true_target); | 
					
						
							|  |  |  |         m_false_target = move(false_target); | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     Optional<Label> m_true_target; | 
					
						
							|  |  |  |     Optional<Label> m_false_target; | 
					
						
							| 
									
										
										
										
											2021-06-04 12:07:38 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  | class JumpConditional final : public Jump { | 
					
						
							| 
									
										
										
										
											2021-06-04 12:20:44 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |     explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {}) | 
					
						
							|  |  |  |         : Jump(Type::JumpConditional, move(true_target), move(false_target)) | 
					
						
							| 
									
										
										
										
											2021-06-04 12:20:44 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-04 12:20:44 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  | class JumpNullish final : public Jump { | 
					
						
							| 
									
										
										
										
											2021-06-08 02:18:47 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |     explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {}) | 
					
						
							|  |  |  |         : Jump(Type::JumpNullish, move(true_target), move(false_target)) | 
					
						
							| 
									
										
										
										
											2021-06-08 02:18:47 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-08 02:18:47 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  | // NOTE: This instruction is variable-width depending on the number of arguments!
 | 
					
						
							| 
									
										
										
										
											2021-06-05 15:15:30 +02:00
										 |  |  | class Call final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-10 23:01:49 +02:00
										 |  |  |     enum class CallType { | 
					
						
							|  |  |  |         Call, | 
					
						
							|  |  |  |         Construct, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Call(CallType type, Register callee, Register this_value, Vector<Register> const& arguments) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::Call) | 
					
						
							| 
									
										
										
										
											2021-06-05 15:15:30 +02:00
										 |  |  |         , m_callee(callee) | 
					
						
							|  |  |  |         , m_this_value(this_value) | 
					
						
							| 
									
										
										
										
											2021-06-10 23:01:49 +02:00
										 |  |  |         , m_type(type) | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         , m_argument_count(arguments.size()) | 
					
						
							| 
									
										
										
										
											2021-06-05 15:15:30 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         for (size_t i = 0; i < m_argument_count; ++i) | 
					
						
							|  |  |  |             m_arguments[i] = arguments[i]; | 
					
						
							| 
									
										
										
										
											2021-06-05 15:15:30 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     size_t length() const { return sizeof(*this) + sizeof(Register) * m_argument_count; } | 
					
						
							| 
									
										
										
										
											2021-06-05 15:15:30 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Register m_callee; | 
					
						
							|  |  |  |     Register m_this_value; | 
					
						
							| 
									
										
										
										
											2021-06-10 23:01:49 +02:00
										 |  |  |     CallType m_type; | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     size_t m_argument_count { 0 }; | 
					
						
							|  |  |  |     Register m_arguments[]; | 
					
						
							| 
									
										
										
										
											2021-06-05 15:15:30 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 00:49:23 +02:00
										 |  |  | class NewFunction final : public Instruction { | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-10 00:49:23 +02:00
										 |  |  |     explicit NewFunction(FunctionNode const& function_node) | 
					
						
							|  |  |  |         : Instruction(Type::NewFunction) | 
					
						
							|  |  |  |         , m_function_node(function_node) | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-06-10 00:49:23 +02:00
										 |  |  |     FunctionNode const& m_function_node; | 
					
						
							| 
									
										
										
										
											2021-06-05 15:14:09 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-05 15:53:36 +02:00
										 |  |  | class Return final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2021-06-09 06:49:58 +04:30
										 |  |  |     constexpr static bool IsTerminator = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 20:58:36 -07:00
										 |  |  |     Return() | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |         : Instruction(Type::Return) | 
					
						
							| 
									
										
										
										
											2021-06-05 15:53:36 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 15:12:43 +02:00
										 |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-05 15:53:36 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 11:40:38 +02:00
										 |  |  | class Increment final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Increment() | 
					
						
							|  |  |  |         : Instruction(Type::Increment) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 11:40:38 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Decrement final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Decrement() | 
					
						
							|  |  |  |         : Instruction(Type::Decrement) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 10:02:01 +02:00
										 |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							| 
									
										
										
										
											2021-06-09 11:40:38 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 18:18:56 +02:00
										 |  |  | class Throw final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     constexpr static bool IsTerminator = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Throw() | 
					
						
							|  |  |  |         : Instruction(Type::Throw) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							|  |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 15:04:38 +02:00
										 |  |  | class EnterUnwindContext final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     EnterUnwindContext(Optional<Label> handler_target, Optional<Label> finalizer_target) | 
					
						
							|  |  |  |         : Instruction(Type::EnterUnwindContext) | 
					
						
							|  |  |  |         , m_handler_target(handler_target) | 
					
						
							|  |  |  |         , m_finalizer_target(finalizer_target) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							|  |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Optional<Label> m_handler_target; | 
					
						
							|  |  |  |     Optional<Label> m_finalizer_target; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class LeaveUnwindContext final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     LeaveUnwindContext() | 
					
						
							|  |  |  |         : Instruction(Type::LeaveUnwindContext) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							|  |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ContinuePendingUnwind final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     constexpr static bool IsTerminator = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ContinuePendingUnwind(Label const& resume_target) | 
					
						
							|  |  |  |         : Instruction(Type::ContinuePendingUnwind) | 
					
						
							|  |  |  |         , m_resume_target(resume_target) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							|  |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Label m_resume_target; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2021-06-10 22:12:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 01:38:30 +04:30
										 |  |  | class Yield final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     constexpr static bool IsTerminator = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     explicit Yield(Label continuation_label) | 
					
						
							|  |  |  |         : Instruction(Type::Yield) | 
					
						
							|  |  |  |         , m_continuation_label(continuation_label) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     explicit Yield(std::nullptr_t) | 
					
						
							|  |  |  |         : Instruction(Type::Yield) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							|  |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Optional<Label> m_continuation_label; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 22:12:21 +02:00
										 |  |  | class PushLexicalEnvironment final : public Instruction { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     PushLexicalEnvironment(HashMap<u32, Variable> variables) | 
					
						
							|  |  |  |         : Instruction(Type::PushLexicalEnvironment) | 
					
						
							|  |  |  |         , m_variables(move(variables)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void execute(Bytecode::Interpreter&) const; | 
					
						
							|  |  |  |     String to_string(Bytecode::Executable const&) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 01:38:30 +04:30
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-06-10 22:12:21 +02:00
										 |  |  |     HashMap<u32, Variable> m_variables; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2021-06-03 10:46:30 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-09 09:19:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace JS::Bytecode { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #define __BYTECODE_OP(op)       \
 | 
					
						
							|  |  |  |     case Instruction::Type::op: \ | 
					
						
							|  |  |  |         return static_cast<Bytecode::Op::op const&>(*this).execute(interpreter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (type()) { | 
					
						
							|  |  |  |         ENUMERATE_BYTECODE_OPS(__BYTECODE_OP) | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef __BYTECODE_OP
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 09:23:38 +02:00
										 |  |  | ALWAYS_INLINE size_t Instruction::length() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (type() == Type::Call) | 
					
						
							|  |  |  |         return static_cast<Op::Call const&>(*this).length(); | 
					
						
							|  |  |  |     else if (type() == Type::NewArray) | 
					
						
							|  |  |  |         return static_cast<Op::NewArray const&>(*this).length(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define __BYTECODE_OP(op) \
 | 
					
						
							|  |  |  |     case Type::op:        \ | 
					
						
							|  |  |  |         return sizeof(Op::op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (type()) { | 
					
						
							|  |  |  |         ENUMERATE_BYTECODE_OPS(__BYTECODE_OP) | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #undef __BYTECODE_OP
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 09:19:34 +02:00
										 |  |  | } |