Op.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  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. 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. 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. 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. 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. NewString(StringTableIndex string)
  116. : Instruction(Type::NewString)
  117. , m_string(move(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. 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. 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 GetByValue final : public Instruction {
  225. public:
  226. explicit GetByValue(Register base)
  227. : Instruction(Type::GetByValue)
  228. , m_base(base)
  229. {
  230. }
  231. void execute(Bytecode::Interpreter&) const;
  232. String to_string(Bytecode::Executable const&) const;
  233. private:
  234. Register m_base;
  235. };
  236. class PutByValue final : public Instruction {
  237. public:
  238. PutByValue(Register base, Register property)
  239. : Instruction(Type::PutByValue)
  240. , m_base(base)
  241. , m_property(property)
  242. {
  243. }
  244. void execute(Bytecode::Interpreter&) const;
  245. String to_string(Bytecode::Executable const&) const;
  246. private:
  247. Register m_base;
  248. Register m_property;
  249. };
  250. class Jump : public Instruction {
  251. public:
  252. constexpr static bool IsTerminator = true;
  253. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  254. : Instruction(type)
  255. , m_true_target(move(taken_target))
  256. , m_false_target(move(nontaken_target))
  257. {
  258. }
  259. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  260. : Instruction(Type::Jump)
  261. , m_true_target(move(taken_target))
  262. , m_false_target(move(nontaken_target))
  263. {
  264. }
  265. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  266. {
  267. m_true_target = move(true_target);
  268. m_false_target = move(false_target);
  269. }
  270. void execute(Bytecode::Interpreter&) const;
  271. String to_string(Bytecode::Executable const&) const;
  272. protected:
  273. Optional<Label> m_true_target;
  274. Optional<Label> m_false_target;
  275. };
  276. class JumpConditional final : public Jump {
  277. public:
  278. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  279. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  280. {
  281. }
  282. void execute(Bytecode::Interpreter&) const;
  283. String to_string(Bytecode::Executable const&) const;
  284. };
  285. class JumpNullish final : public Jump {
  286. public:
  287. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  288. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  289. {
  290. }
  291. void execute(Bytecode::Interpreter&) const;
  292. String to_string(Bytecode::Executable const&) const;
  293. };
  294. // NOTE: This instruction is variable-width depending on the number of arguments!
  295. class Call final : public Instruction {
  296. public:
  297. enum class CallType {
  298. Call,
  299. Construct,
  300. };
  301. Call(CallType type, Register callee, Register this_value, Vector<Register> const& arguments)
  302. : Instruction(Type::Call)
  303. , m_callee(callee)
  304. , m_this_value(this_value)
  305. , m_type(type)
  306. , m_argument_count(arguments.size())
  307. {
  308. for (size_t i = 0; i < m_argument_count; ++i)
  309. m_arguments[i] = arguments[i];
  310. }
  311. void execute(Bytecode::Interpreter&) const;
  312. String to_string(Bytecode::Executable const&) const;
  313. size_t length() const { return sizeof(*this) + sizeof(Register) * m_argument_count; }
  314. private:
  315. Register m_callee;
  316. Register m_this_value;
  317. CallType m_type;
  318. size_t m_argument_count { 0 };
  319. Register m_arguments[];
  320. };
  321. class NewFunction final : public Instruction {
  322. public:
  323. explicit NewFunction(FunctionNode const& function_node)
  324. : Instruction(Type::NewFunction)
  325. , m_function_node(function_node)
  326. {
  327. }
  328. void execute(Bytecode::Interpreter&) const;
  329. String to_string(Bytecode::Executable const&) const;
  330. private:
  331. FunctionNode const& m_function_node;
  332. };
  333. class Return final : public Instruction {
  334. public:
  335. constexpr static bool IsTerminator = true;
  336. Return()
  337. : Instruction(Type::Return)
  338. {
  339. }
  340. void execute(Bytecode::Interpreter&) const;
  341. String to_string(Bytecode::Executable const&) const;
  342. };
  343. class Increment final : public Instruction {
  344. public:
  345. Increment()
  346. : Instruction(Type::Increment)
  347. {
  348. }
  349. void execute(Bytecode::Interpreter&) const;
  350. String to_string(Bytecode::Executable const&) const;
  351. };
  352. class Decrement final : public Instruction {
  353. public:
  354. Decrement()
  355. : Instruction(Type::Decrement)
  356. {
  357. }
  358. void execute(Bytecode::Interpreter&) const;
  359. String to_string(Bytecode::Executable const&) const;
  360. };
  361. class Throw final : public Instruction {
  362. public:
  363. constexpr static bool IsTerminator = true;
  364. Throw()
  365. : Instruction(Type::Throw)
  366. {
  367. }
  368. void execute(Bytecode::Interpreter&) const;
  369. String to_string(Bytecode::Executable const&) const;
  370. };
  371. class EnterUnwindContext final : public Instruction {
  372. public:
  373. EnterUnwindContext(Optional<Label> handler_target, Optional<Label> finalizer_target)
  374. : Instruction(Type::EnterUnwindContext)
  375. , m_handler_target(handler_target)
  376. , m_finalizer_target(finalizer_target)
  377. {
  378. }
  379. void execute(Bytecode::Interpreter&) const;
  380. String to_string(Bytecode::Executable const&) const;
  381. private:
  382. Optional<Label> m_handler_target;
  383. Optional<Label> m_finalizer_target;
  384. };
  385. class LeaveUnwindContext final : public Instruction {
  386. public:
  387. LeaveUnwindContext()
  388. : Instruction(Type::LeaveUnwindContext)
  389. {
  390. }
  391. void execute(Bytecode::Interpreter&) const;
  392. String to_string(Bytecode::Executable const&) const;
  393. };
  394. class ContinuePendingUnwind final : public Instruction {
  395. public:
  396. constexpr static bool IsTerminator = true;
  397. ContinuePendingUnwind(Label const& resume_target)
  398. : Instruction(Type::ContinuePendingUnwind)
  399. , m_resume_target(resume_target)
  400. {
  401. }
  402. void execute(Bytecode::Interpreter&) const;
  403. String to_string(Bytecode::Executable const&) const;
  404. private:
  405. Label m_resume_target;
  406. };
  407. class Yield final : public Instruction {
  408. public:
  409. constexpr static bool IsTerminator = true;
  410. explicit Yield(Label continuation_label)
  411. : Instruction(Type::Yield)
  412. , m_continuation_label(continuation_label)
  413. {
  414. }
  415. explicit Yield(std::nullptr_t)
  416. : Instruction(Type::Yield)
  417. {
  418. }
  419. void execute(Bytecode::Interpreter&) const;
  420. String to_string(Bytecode::Executable const&) const;
  421. private:
  422. Optional<Label> m_continuation_label;
  423. };
  424. class PushLexicalEnvironment final : public Instruction {
  425. public:
  426. PushLexicalEnvironment(HashMap<u32, Variable> variables)
  427. : Instruction(Type::PushLexicalEnvironment)
  428. , m_variables(move(variables))
  429. {
  430. }
  431. void execute(Bytecode::Interpreter&) const;
  432. String to_string(Bytecode::Executable const&) const;
  433. private:
  434. HashMap<u32, Variable> m_variables;
  435. };
  436. }
  437. namespace JS::Bytecode {
  438. ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const
  439. {
  440. #define __BYTECODE_OP(op) \
  441. case Instruction::Type::op: \
  442. return static_cast<Bytecode::Op::op const&>(*this).execute(interpreter);
  443. switch (type()) {
  444. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  445. default:
  446. VERIFY_NOT_REACHED();
  447. }
  448. #undef __BYTECODE_OP
  449. }
  450. ALWAYS_INLINE size_t Instruction::length() const
  451. {
  452. if (type() == Type::Call)
  453. return static_cast<Op::Call const&>(*this).length();
  454. else if (type() == Type::NewArray)
  455. return static_cast<Op::NewArray const&>(*this).length();
  456. #define __BYTECODE_OP(op) \
  457. case Type::op: \
  458. return sizeof(Op::op);
  459. switch (type()) {
  460. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  461. default:
  462. VERIFY_NOT_REACHED();
  463. }
  464. #undef __BYTECODE_OP
  465. }
  466. }