Op.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  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/ScopeObject.h>
  16. #include <LibJS/Runtime/Value.h>
  17. namespace JS::Bytecode::Op {
  18. class Load final : public Instruction {
  19. public:
  20. explicit Load(Register src)
  21. : Instruction(Type::Load)
  22. , m_src(src)
  23. {
  24. }
  25. void execute(Bytecode::Interpreter&) const;
  26. String to_string(Bytecode::Executable const&) const;
  27. private:
  28. Register m_src;
  29. };
  30. class LoadImmediate final : public Instruction {
  31. public:
  32. explicit LoadImmediate(Value value)
  33. : Instruction(Type::LoadImmediate)
  34. , m_value(value)
  35. {
  36. }
  37. void execute(Bytecode::Interpreter&) const;
  38. String to_string(Bytecode::Executable const&) const;
  39. private:
  40. Value m_value;
  41. };
  42. class Store final : public Instruction {
  43. public:
  44. explicit Store(Register dst)
  45. : Instruction(Type::Store)
  46. , m_dst(dst)
  47. {
  48. }
  49. void execute(Bytecode::Interpreter&) const;
  50. String to_string(Bytecode::Executable const&) const;
  51. private:
  52. Register m_dst;
  53. };
  54. #define JS_ENUMERATE_COMMON_BINARY_OPS(O) \
  55. O(Add, add) \
  56. O(Sub, sub) \
  57. O(Mul, mul) \
  58. O(Div, div) \
  59. O(Exp, exp) \
  60. O(Mod, mod) \
  61. O(In, in) \
  62. O(InstanceOf, instance_of) \
  63. O(GreaterThan, greater_than) \
  64. O(GreaterThanEquals, greater_than_equals) \
  65. O(LessThan, less_than) \
  66. O(LessThanEquals, less_than_equals) \
  67. O(AbstractInequals, abstract_inequals) \
  68. O(AbstractEquals, abstract_equals) \
  69. O(TypedInequals, typed_inequals) \
  70. O(TypedEquals, typed_equals) \
  71. O(BitwiseAnd, bitwise_and) \
  72. O(BitwiseOr, bitwise_or) \
  73. O(BitwiseXor, bitwise_xor) \
  74. O(LeftShift, left_shift) \
  75. O(RightShift, right_shift) \
  76. O(UnsignedRightShift, unsigned_right_shift)
  77. #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  78. class OpTitleCase final : public Instruction { \
  79. public: \
  80. explicit OpTitleCase(Register lhs_reg) \
  81. : Instruction(Type::OpTitleCase) \
  82. , m_lhs_reg(lhs_reg) \
  83. { \
  84. } \
  85. \
  86. void execute(Bytecode::Interpreter&) const; \
  87. String to_string(Bytecode::Executable const&) const; \
  88. \
  89. private: \
  90. Register m_lhs_reg; \
  91. };
  92. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP)
  93. #undef JS_DECLARE_COMMON_BINARY_OP
  94. #define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
  95. O(BitwiseNot, bitwise_not) \
  96. O(Not, not_) \
  97. O(UnaryPlus, unary_plus) \
  98. O(UnaryMinus, unary_minus) \
  99. O(Typeof, typeof_)
  100. #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  101. class OpTitleCase final : public Instruction { \
  102. public: \
  103. OpTitleCase() \
  104. : Instruction(Type::OpTitleCase) \
  105. { \
  106. } \
  107. \
  108. void execute(Bytecode::Interpreter&) const; \
  109. String to_string(Bytecode::Executable const&) const; \
  110. };
  111. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
  112. #undef JS_DECLARE_COMMON_UNARY_OP
  113. class NewString final : public Instruction {
  114. public:
  115. explicit NewString(StringTableIndex string)
  116. : Instruction(Type::NewString)
  117. , m_string(string)
  118. {
  119. }
  120. void execute(Bytecode::Interpreter&) const;
  121. String to_string(Bytecode::Executable const&) const;
  122. private:
  123. StringTableIndex m_string;
  124. };
  125. class NewObject final : public Instruction {
  126. public:
  127. NewObject()
  128. : Instruction(Type::NewObject)
  129. {
  130. }
  131. void execute(Bytecode::Interpreter&) const;
  132. String to_string(Bytecode::Executable const&) const;
  133. };
  134. class NewBigInt final : public Instruction {
  135. public:
  136. explicit NewBigInt(Crypto::SignedBigInteger bigint)
  137. : Instruction(Type::NewBigInt)
  138. , m_bigint(move(bigint))
  139. {
  140. }
  141. void execute(Bytecode::Interpreter&) const;
  142. String to_string(Bytecode::Executable const&) const;
  143. private:
  144. Crypto::SignedBigInteger m_bigint;
  145. };
  146. // NOTE: This instruction is variable-width depending on the number of elements!
  147. class NewArray final : public Instruction {
  148. public:
  149. explicit NewArray(Vector<Register> const& elements)
  150. : Instruction(Type::NewArray)
  151. , m_element_count(elements.size())
  152. {
  153. for (size_t i = 0; i < m_element_count; ++i)
  154. m_elements[i] = elements[i];
  155. }
  156. void execute(Bytecode::Interpreter&) const;
  157. String to_string(Bytecode::Executable const&) const;
  158. size_t length() const { return sizeof(*this) + sizeof(Register) * m_element_count; }
  159. private:
  160. size_t m_element_count { 0 };
  161. Register m_elements[];
  162. };
  163. class ConcatString final : public Instruction {
  164. public:
  165. explicit ConcatString(Register lhs)
  166. : Instruction(Type::ConcatString)
  167. , m_lhs(lhs)
  168. {
  169. }
  170. void execute(Bytecode::Interpreter&) const;
  171. String to_string(Bytecode::Executable const&) const;
  172. private:
  173. Register m_lhs;
  174. };
  175. class SetVariable final : public Instruction {
  176. public:
  177. explicit SetVariable(StringTableIndex identifier)
  178. : Instruction(Type::SetVariable)
  179. , m_identifier(identifier)
  180. {
  181. }
  182. void execute(Bytecode::Interpreter&) const;
  183. String to_string(Bytecode::Executable const&) const;
  184. private:
  185. StringTableIndex m_identifier;
  186. };
  187. class GetVariable final : public Instruction {
  188. public:
  189. explicit GetVariable(StringTableIndex identifier)
  190. : Instruction(Type::GetVariable)
  191. , m_identifier(identifier)
  192. {
  193. }
  194. void execute(Bytecode::Interpreter&) const;
  195. String to_string(Bytecode::Executable const&) const;
  196. private:
  197. StringTableIndex m_identifier;
  198. };
  199. class GetById final : public Instruction {
  200. public:
  201. explicit GetById(StringTableIndex property)
  202. : Instruction(Type::GetById)
  203. , m_property(property)
  204. {
  205. }
  206. void execute(Bytecode::Interpreter&) const;
  207. String to_string(Bytecode::Executable const&) const;
  208. private:
  209. StringTableIndex m_property;
  210. };
  211. class PutById final : public Instruction {
  212. public:
  213. explicit PutById(Register base, StringTableIndex property)
  214. : Instruction(Type::PutById)
  215. , m_base(base)
  216. , m_property(property)
  217. {
  218. }
  219. void execute(Bytecode::Interpreter&) const;
  220. String to_string(Bytecode::Executable const&) const;
  221. private:
  222. Register m_base;
  223. StringTableIndex m_property;
  224. };
  225. class GetByValue final : public Instruction {
  226. public:
  227. explicit GetByValue(Register base)
  228. : Instruction(Type::GetByValue)
  229. , m_base(base)
  230. {
  231. }
  232. void execute(Bytecode::Interpreter&) const;
  233. String to_string(Bytecode::Executable const&) const;
  234. private:
  235. Register m_base;
  236. };
  237. class PutByValue final : public Instruction {
  238. public:
  239. PutByValue(Register base, Register property)
  240. : Instruction(Type::PutByValue)
  241. , m_base(base)
  242. , m_property(property)
  243. {
  244. }
  245. void execute(Bytecode::Interpreter&) const;
  246. String to_string(Bytecode::Executable const&) const;
  247. private:
  248. Register m_base;
  249. Register m_property;
  250. };
  251. class Jump : public Instruction {
  252. public:
  253. constexpr static bool IsTerminator = true;
  254. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  255. : Instruction(type)
  256. , m_true_target(move(taken_target))
  257. , m_false_target(move(nontaken_target))
  258. {
  259. }
  260. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  261. : Instruction(Type::Jump)
  262. , m_true_target(move(taken_target))
  263. , m_false_target(move(nontaken_target))
  264. {
  265. }
  266. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  267. {
  268. m_true_target = move(true_target);
  269. m_false_target = move(false_target);
  270. }
  271. void execute(Bytecode::Interpreter&) const;
  272. String to_string(Bytecode::Executable const&) const;
  273. protected:
  274. Optional<Label> m_true_target;
  275. Optional<Label> m_false_target;
  276. };
  277. class JumpConditional final : public Jump {
  278. public:
  279. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  280. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  281. {
  282. }
  283. void execute(Bytecode::Interpreter&) const;
  284. String to_string(Bytecode::Executable const&) const;
  285. };
  286. class JumpNullish final : public Jump {
  287. public:
  288. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  289. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  290. {
  291. }
  292. void execute(Bytecode::Interpreter&) const;
  293. String to_string(Bytecode::Executable const&) const;
  294. };
  295. // NOTE: This instruction is variable-width depending on the number of arguments!
  296. class Call final : public Instruction {
  297. public:
  298. enum class CallType {
  299. Call,
  300. Construct,
  301. };
  302. Call(CallType type, Register callee, Register this_value, Vector<Register> const& arguments)
  303. : Instruction(Type::Call)
  304. , m_callee(callee)
  305. , m_this_value(this_value)
  306. , m_type(type)
  307. , m_argument_count(arguments.size())
  308. {
  309. for (size_t i = 0; i < m_argument_count; ++i)
  310. m_arguments[i] = arguments[i];
  311. }
  312. void execute(Bytecode::Interpreter&) const;
  313. String to_string(Bytecode::Executable const&) const;
  314. size_t length() const { return sizeof(*this) + sizeof(Register) * m_argument_count; }
  315. private:
  316. Register m_callee;
  317. Register m_this_value;
  318. CallType m_type;
  319. size_t m_argument_count { 0 };
  320. Register m_arguments[];
  321. };
  322. class NewFunction final : public Instruction {
  323. public:
  324. explicit NewFunction(FunctionNode const& function_node)
  325. : Instruction(Type::NewFunction)
  326. , m_function_node(function_node)
  327. {
  328. }
  329. void execute(Bytecode::Interpreter&) const;
  330. String to_string(Bytecode::Executable const&) const;
  331. private:
  332. FunctionNode const& m_function_node;
  333. };
  334. class Return final : public Instruction {
  335. public:
  336. constexpr static bool IsTerminator = true;
  337. Return()
  338. : Instruction(Type::Return)
  339. {
  340. }
  341. void execute(Bytecode::Interpreter&) const;
  342. String to_string(Bytecode::Executable const&) const;
  343. };
  344. class Increment final : public Instruction {
  345. public:
  346. Increment()
  347. : Instruction(Type::Increment)
  348. {
  349. }
  350. void execute(Bytecode::Interpreter&) const;
  351. String to_string(Bytecode::Executable const&) const;
  352. };
  353. class Decrement final : public Instruction {
  354. public:
  355. Decrement()
  356. : Instruction(Type::Decrement)
  357. {
  358. }
  359. void execute(Bytecode::Interpreter&) const;
  360. String to_string(Bytecode::Executable const&) const;
  361. };
  362. class Throw final : public Instruction {
  363. public:
  364. constexpr static bool IsTerminator = true;
  365. Throw()
  366. : Instruction(Type::Throw)
  367. {
  368. }
  369. void execute(Bytecode::Interpreter&) const;
  370. String to_string(Bytecode::Executable const&) const;
  371. };
  372. class EnterUnwindContext final : public Instruction {
  373. public:
  374. constexpr static bool IsTerminator = true;
  375. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  376. : Instruction(Type::EnterUnwindContext)
  377. , m_entry_point(move(entry_point))
  378. , m_handler_target(move(handler_target))
  379. , m_finalizer_target(move(finalizer_target))
  380. {
  381. }
  382. void execute(Bytecode::Interpreter&) const;
  383. String to_string(Bytecode::Executable const&) const;
  384. private:
  385. Label m_entry_point;
  386. Optional<Label> m_handler_target;
  387. Optional<Label> m_finalizer_target;
  388. };
  389. class LeaveUnwindContext final : public Instruction {
  390. public:
  391. LeaveUnwindContext()
  392. : Instruction(Type::LeaveUnwindContext)
  393. {
  394. }
  395. void execute(Bytecode::Interpreter&) const;
  396. String to_string(Bytecode::Executable const&) const;
  397. };
  398. class ContinuePendingUnwind final : public Instruction {
  399. public:
  400. constexpr static bool IsTerminator = true;
  401. explicit ContinuePendingUnwind(Label resume_target)
  402. : Instruction(Type::ContinuePendingUnwind)
  403. , m_resume_target(resume_target)
  404. {
  405. }
  406. void execute(Bytecode::Interpreter&) const;
  407. String to_string(Bytecode::Executable const&) const;
  408. private:
  409. Label m_resume_target;
  410. };
  411. class Yield final : public Instruction {
  412. public:
  413. constexpr static bool IsTerminator = true;
  414. explicit Yield(Label continuation_label)
  415. : Instruction(Type::Yield)
  416. , m_continuation_label(continuation_label)
  417. {
  418. }
  419. explicit Yield(std::nullptr_t)
  420. : Instruction(Type::Yield)
  421. {
  422. }
  423. void execute(Bytecode::Interpreter&) const;
  424. String to_string(Bytecode::Executable const&) const;
  425. private:
  426. Optional<Label> m_continuation_label;
  427. };
  428. class PushLexicalEnvironment final : public Instruction {
  429. public:
  430. explicit PushLexicalEnvironment(HashMap<u32, Variable> variables)
  431. : Instruction(Type::PushLexicalEnvironment)
  432. , m_variables(move(variables))
  433. {
  434. }
  435. void execute(Bytecode::Interpreter&) const;
  436. String to_string(Bytecode::Executable const&) const;
  437. private:
  438. HashMap<u32, Variable> m_variables;
  439. };
  440. class LoadArgument final : public Instruction {
  441. public:
  442. explicit LoadArgument(size_t index)
  443. : Instruction(Type::LoadArgument)
  444. , m_index(index)
  445. {
  446. }
  447. void execute(Bytecode::Interpreter&) const;
  448. String to_string(Bytecode::Executable const&) const;
  449. private:
  450. size_t m_index { 0 };
  451. };
  452. }
  453. namespace JS::Bytecode {
  454. ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const
  455. {
  456. #define __BYTECODE_OP(op) \
  457. case Instruction::Type::op: \
  458. return static_cast<Bytecode::Op::op const&>(*this).execute(interpreter);
  459. switch (type()) {
  460. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  461. default:
  462. VERIFY_NOT_REACHED();
  463. }
  464. #undef __BYTECODE_OP
  465. }
  466. ALWAYS_INLINE size_t Instruction::length() const
  467. {
  468. if (type() == Type::Call)
  469. return static_cast<Op::Call const&>(*this).length();
  470. else if (type() == Type::NewArray)
  471. return static_cast<Op::NewArray const&>(*this).length();
  472. #define __BYTECODE_OP(op) \
  473. case Type::op: \
  474. return sizeof(Op::op);
  475. switch (type()) {
  476. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  477. default:
  478. VERIFY_NOT_REACHED();
  479. }
  480. #undef __BYTECODE_OP
  481. }
  482. }