Op.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * Copyright (c) 2021, 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. #pragma once
  9. #include <LibCrypto/BigInt/SignedBigInteger.h>
  10. #include <LibJS/Bytecode/Instruction.h>
  11. #include <LibJS/Bytecode/Label.h>
  12. #include <LibJS/Bytecode/Register.h>
  13. #include <LibJS/Bytecode/StringTable.h>
  14. #include <LibJS/Heap/Cell.h>
  15. #include <LibJS/Runtime/Value.h>
  16. namespace JS::Bytecode::Op {
  17. class Load final : public Instruction {
  18. public:
  19. Load(Register src)
  20. : Instruction(Type::Load)
  21. , m_src(src)
  22. {
  23. }
  24. void execute(Bytecode::Interpreter&) const;
  25. String to_string(Bytecode::Executable const&) const;
  26. private:
  27. Register m_src;
  28. };
  29. class LoadImmediate final : public Instruction {
  30. public:
  31. LoadImmediate(Value value)
  32. : Instruction(Type::LoadImmediate)
  33. , m_value(value)
  34. {
  35. }
  36. void execute(Bytecode::Interpreter&) const;
  37. String to_string(Bytecode::Executable const&) const;
  38. private:
  39. Value m_value;
  40. };
  41. class Store final : public Instruction {
  42. public:
  43. Store(Register dst)
  44. : Instruction(Type::Store)
  45. , m_dst(dst)
  46. {
  47. }
  48. void execute(Bytecode::Interpreter&) const;
  49. String to_string(Bytecode::Executable const&) const;
  50. private:
  51. Register m_dst;
  52. };
  53. #define JS_ENUMERATE_COMMON_BINARY_OPS(O) \
  54. O(Add, add) \
  55. O(Sub, sub) \
  56. O(Mul, mul) \
  57. O(Div, div) \
  58. O(Exp, exp) \
  59. O(Mod, mod) \
  60. O(In, in) \
  61. O(InstanceOf, instance_of) \
  62. O(GreaterThan, greater_than) \
  63. O(GreaterThanEquals, greater_than_equals) \
  64. O(LessThan, less_than) \
  65. O(LessThanEquals, less_than_equals) \
  66. O(AbstractInequals, abstract_inequals) \
  67. O(AbstractEquals, abstract_equals) \
  68. O(TypedInequals, typed_inequals) \
  69. O(TypedEquals, typed_equals) \
  70. O(BitwiseAnd, bitwise_and) \
  71. O(BitwiseOr, bitwise_or) \
  72. O(BitwiseXor, bitwise_xor) \
  73. O(LeftShift, left_shift) \
  74. O(RightShift, right_shift) \
  75. O(UnsignedRightShift, unsigned_right_shift)
  76. #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  77. class OpTitleCase final : public Instruction { \
  78. public: \
  79. OpTitleCase(Register lhs_reg) \
  80. : Instruction(Type::OpTitleCase) \
  81. , m_lhs_reg(lhs_reg) \
  82. { \
  83. } \
  84. \
  85. void execute(Bytecode::Interpreter&) const; \
  86. String to_string(Bytecode::Executable const&) const; \
  87. \
  88. private: \
  89. Register m_lhs_reg; \
  90. };
  91. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP)
  92. #undef JS_DECLARE_COMMON_BINARY_OP
  93. #define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
  94. O(BitwiseNot, bitwise_not) \
  95. O(Not, not_) \
  96. O(UnaryPlus, unary_plus) \
  97. O(UnaryMinus, unary_minus) \
  98. O(Typeof, typeof_)
  99. #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  100. class OpTitleCase final : public Instruction { \
  101. public: \
  102. OpTitleCase() \
  103. : Instruction(Type::OpTitleCase) \
  104. { \
  105. } \
  106. \
  107. void execute(Bytecode::Interpreter&) const; \
  108. String to_string(Bytecode::Executable const&) const; \
  109. };
  110. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
  111. #undef JS_DECLARE_COMMON_UNARY_OP
  112. class NewString final : public Instruction {
  113. public:
  114. NewString(StringTableIndex string)
  115. : Instruction(Type::NewString)
  116. , m_string(move(string))
  117. {
  118. }
  119. void execute(Bytecode::Interpreter&) const;
  120. String to_string(Bytecode::Executable const&) const;
  121. private:
  122. StringTableIndex m_string;
  123. };
  124. class NewObject final : public Instruction {
  125. public:
  126. NewObject()
  127. : Instruction(Type::NewObject)
  128. {
  129. }
  130. void execute(Bytecode::Interpreter&) const;
  131. String to_string(Bytecode::Executable const&) const;
  132. };
  133. class NewBigInt final : public Instruction {
  134. public:
  135. explicit NewBigInt(Crypto::SignedBigInteger bigint)
  136. : Instruction(Type::NewBigInt)
  137. , m_bigint(move(bigint))
  138. {
  139. }
  140. void execute(Bytecode::Interpreter&) const;
  141. String to_string(Bytecode::Executable const&) const;
  142. private:
  143. Crypto::SignedBigInteger m_bigint;
  144. };
  145. // NOTE: This instruction is variable-width depending on the number of elements!
  146. class NewArray final : public Instruction {
  147. public:
  148. NewArray(Vector<Register> const& elements)
  149. : Instruction(Type::NewArray)
  150. , m_element_count(elements.size())
  151. {
  152. for (size_t i = 0; i < m_element_count; ++i)
  153. m_elements[i] = elements[i];
  154. }
  155. void execute(Bytecode::Interpreter&) const;
  156. String to_string(Bytecode::Executable const&) const;
  157. size_t length() const { return sizeof(*this) + sizeof(Register) * m_element_count; }
  158. private:
  159. size_t m_element_count { 0 };
  160. Register m_elements[];
  161. };
  162. class ConcatString final : public Instruction {
  163. public:
  164. ConcatString(Register lhs)
  165. : Instruction(Type::ConcatString)
  166. , m_lhs(lhs)
  167. {
  168. }
  169. void execute(Bytecode::Interpreter&) const;
  170. String to_string(Bytecode::Executable const&) const;
  171. private:
  172. Register m_lhs;
  173. };
  174. class SetVariable final : public Instruction {
  175. public:
  176. SetVariable(StringTableIndex identifier)
  177. : Instruction(Type::SetVariable)
  178. , m_identifier(move(identifier))
  179. {
  180. }
  181. void execute(Bytecode::Interpreter&) const;
  182. String to_string(Bytecode::Executable const&) const;
  183. private:
  184. StringTableIndex m_identifier;
  185. };
  186. class GetVariable final : public Instruction {
  187. public:
  188. GetVariable(StringTableIndex identifier)
  189. : Instruction(Type::GetVariable)
  190. , m_identifier(move(identifier))
  191. {
  192. }
  193. void execute(Bytecode::Interpreter&) const;
  194. String to_string(Bytecode::Executable const&) const;
  195. private:
  196. StringTableIndex m_identifier;
  197. };
  198. class GetById final : public Instruction {
  199. public:
  200. GetById(StringTableIndex property)
  201. : Instruction(Type::GetById)
  202. , m_property(move(property))
  203. {
  204. }
  205. void execute(Bytecode::Interpreter&) const;
  206. String to_string(Bytecode::Executable const&) const;
  207. private:
  208. StringTableIndex m_property;
  209. };
  210. class PutById final : public Instruction {
  211. public:
  212. PutById(Register base, StringTableIndex property)
  213. : Instruction(Type::PutById)
  214. , m_base(base)
  215. , m_property(move(property))
  216. {
  217. }
  218. void execute(Bytecode::Interpreter&) const;
  219. String to_string(Bytecode::Executable const&) const;
  220. private:
  221. Register m_base;
  222. StringTableIndex m_property;
  223. };
  224. class Jump : public Instruction {
  225. public:
  226. constexpr static bool IsTerminator = true;
  227. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  228. : Instruction(type)
  229. , m_true_target(move(taken_target))
  230. , m_false_target(move(nontaken_target))
  231. {
  232. }
  233. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  234. : Instruction(Type::Jump)
  235. , m_true_target(move(taken_target))
  236. , m_false_target(move(nontaken_target))
  237. {
  238. }
  239. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  240. {
  241. m_true_target = move(true_target);
  242. m_false_target = move(false_target);
  243. }
  244. void execute(Bytecode::Interpreter&) const;
  245. String to_string(Bytecode::Executable const&) const;
  246. protected:
  247. Optional<Label> m_true_target;
  248. Optional<Label> m_false_target;
  249. };
  250. class JumpConditional final : public Jump {
  251. public:
  252. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  253. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  254. {
  255. }
  256. void execute(Bytecode::Interpreter&) const;
  257. String to_string(Bytecode::Executable const&) const;
  258. };
  259. class JumpNullish final : public Jump {
  260. public:
  261. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  262. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  263. {
  264. }
  265. void execute(Bytecode::Interpreter&) const;
  266. String to_string(Bytecode::Executable const&) const;
  267. };
  268. // NOTE: This instruction is variable-width depending on the number of arguments!
  269. class Call final : public Instruction {
  270. public:
  271. Call(Register callee, Register this_value, Vector<Register> const& arguments)
  272. : Instruction(Type::Call)
  273. , m_callee(callee)
  274. , m_this_value(this_value)
  275. , m_argument_count(arguments.size())
  276. {
  277. for (size_t i = 0; i < m_argument_count; ++i)
  278. m_arguments[i] = arguments[i];
  279. }
  280. void execute(Bytecode::Interpreter&) const;
  281. String to_string(Bytecode::Executable const&) const;
  282. size_t length() const { return sizeof(*this) + sizeof(Register) * m_argument_count; }
  283. private:
  284. Register m_callee;
  285. Register m_this_value;
  286. size_t m_argument_count { 0 };
  287. Register m_arguments[];
  288. };
  289. class EnterScope final : public Instruction {
  290. public:
  291. explicit EnterScope(ScopeNode const& scope_node)
  292. : Instruction(Type::EnterScope)
  293. , m_scope_node(scope_node)
  294. {
  295. }
  296. void execute(Bytecode::Interpreter&) const;
  297. String to_string(Bytecode::Executable const&) const;
  298. private:
  299. ScopeNode const& m_scope_node;
  300. };
  301. class Return final : public Instruction {
  302. public:
  303. constexpr static bool IsTerminator = true;
  304. Return()
  305. : Instruction(Type::Return)
  306. {
  307. }
  308. void execute(Bytecode::Interpreter&) const;
  309. String to_string(Bytecode::Executable const&) const;
  310. };
  311. class Increment final : public Instruction {
  312. public:
  313. Increment()
  314. : Instruction(Type::Increment)
  315. {
  316. }
  317. void execute(Bytecode::Interpreter&) const;
  318. String to_string(Bytecode::Executable const&) const;
  319. };
  320. class Decrement final : public Instruction {
  321. public:
  322. Decrement()
  323. : Instruction(Type::Decrement)
  324. {
  325. }
  326. void execute(Bytecode::Interpreter&) const;
  327. String to_string(Bytecode::Executable const&) const;
  328. };
  329. class Throw final : public Instruction {
  330. public:
  331. constexpr static bool IsTerminator = true;
  332. Throw()
  333. : Instruction(Type::Throw)
  334. {
  335. }
  336. void execute(Bytecode::Interpreter&) const;
  337. String to_string(Bytecode::Executable const&) const;
  338. };
  339. }
  340. namespace JS::Bytecode {
  341. ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const
  342. {
  343. #define __BYTECODE_OP(op) \
  344. case Instruction::Type::op: \
  345. return static_cast<Bytecode::Op::op const&>(*this).execute(interpreter);
  346. switch (type()) {
  347. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  348. default:
  349. VERIFY_NOT_REACHED();
  350. }
  351. #undef __BYTECODE_OP
  352. }
  353. ALWAYS_INLINE size_t Instruction::length() const
  354. {
  355. if (type() == Type::Call)
  356. return static_cast<Op::Call const&>(*this).length();
  357. else if (type() == Type::NewArray)
  358. return static_cast<Op::NewArray const&>(*this).length();
  359. #define __BYTECODE_OP(op) \
  360. case Type::op: \
  361. return sizeof(Op::op);
  362. switch (type()) {
  363. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  364. default:
  365. VERIFY_NOT_REACHED();
  366. }
  367. #undef __BYTECODE_OP
  368. }
  369. }