Op.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  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/IdentifierTable.h>
  11. #include <LibJS/Bytecode/Instruction.h>
  12. #include <LibJS/Bytecode/Label.h>
  13. #include <LibJS/Bytecode/Register.h>
  14. #include <LibJS/Bytecode/StringTable.h>
  15. #include <LibJS/Heap/Cell.h>
  16. #include <LibJS/Runtime/Environment.h>
  17. #include <LibJS/Runtime/EnvironmentCoordinate.h>
  18. #include <LibJS/Runtime/Value.h>
  19. namespace JS::Bytecode::Op {
  20. class Load final : public Instruction {
  21. public:
  22. explicit Load(Register src)
  23. : Instruction(Type::Load)
  24. , m_src(src)
  25. {
  26. }
  27. void execute_impl(Bytecode::Interpreter&) const;
  28. String to_string_impl(Bytecode::Executable const&) const;
  29. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  30. private:
  31. Register m_src;
  32. };
  33. class LoadImmediate final : public Instruction {
  34. public:
  35. explicit LoadImmediate(Value value)
  36. : Instruction(Type::LoadImmediate)
  37. , m_value(value)
  38. {
  39. }
  40. void execute_impl(Bytecode::Interpreter&) const;
  41. String to_string_impl(Bytecode::Executable const&) const;
  42. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  43. private:
  44. Value m_value;
  45. };
  46. class Store final : public Instruction {
  47. public:
  48. explicit Store(Register dst)
  49. : Instruction(Type::Store)
  50. , m_dst(dst)
  51. {
  52. }
  53. void execute_impl(Bytecode::Interpreter&) const;
  54. String to_string_impl(Bytecode::Executable const&) const;
  55. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  56. private:
  57. Register m_dst;
  58. };
  59. #define JS_ENUMERATE_COMMON_BINARY_OPS(O) \
  60. O(Add, add) \
  61. O(Sub, sub) \
  62. O(Mul, mul) \
  63. O(Div, div) \
  64. O(Exp, exp) \
  65. O(Mod, mod) \
  66. O(In, in) \
  67. O(InstanceOf, instance_of) \
  68. O(GreaterThan, greater_than) \
  69. O(GreaterThanEquals, greater_than_equals) \
  70. O(LessThan, less_than) \
  71. O(LessThanEquals, less_than_equals) \
  72. O(LooselyInequals, abstract_inequals) \
  73. O(LooselyEquals, abstract_equals) \
  74. O(StrictlyInequals, typed_inequals) \
  75. O(StrictlyEquals, typed_equals) \
  76. O(BitwiseAnd, bitwise_and) \
  77. O(BitwiseOr, bitwise_or) \
  78. O(BitwiseXor, bitwise_xor) \
  79. O(LeftShift, left_shift) \
  80. O(RightShift, right_shift) \
  81. O(UnsignedRightShift, unsigned_right_shift)
  82. #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  83. class OpTitleCase final : public Instruction { \
  84. public: \
  85. explicit OpTitleCase(Register lhs_reg) \
  86. : Instruction(Type::OpTitleCase) \
  87. , m_lhs_reg(lhs_reg) \
  88. { \
  89. } \
  90. \
  91. void execute_impl(Bytecode::Interpreter&) const; \
  92. String to_string_impl(Bytecode::Executable const&) const; \
  93. void replace_references_impl(BasicBlock const&, BasicBlock const&) { } \
  94. \
  95. private: \
  96. Register m_lhs_reg; \
  97. };
  98. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP)
  99. #undef JS_DECLARE_COMMON_BINARY_OP
  100. #define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
  101. O(BitwiseNot, bitwise_not) \
  102. O(Not, not_) \
  103. O(UnaryPlus, unary_plus) \
  104. O(UnaryMinus, unary_minus) \
  105. O(Typeof, typeof_)
  106. #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  107. class OpTitleCase final : public Instruction { \
  108. public: \
  109. OpTitleCase() \
  110. : Instruction(Type::OpTitleCase) \
  111. { \
  112. } \
  113. \
  114. void execute_impl(Bytecode::Interpreter&) const; \
  115. String to_string_impl(Bytecode::Executable const&) const; \
  116. void replace_references_impl(BasicBlock const&, BasicBlock const&) { } \
  117. };
  118. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
  119. #undef JS_DECLARE_COMMON_UNARY_OP
  120. class NewString final : public Instruction {
  121. public:
  122. explicit NewString(StringTableIndex string)
  123. : Instruction(Type::NewString)
  124. , m_string(string)
  125. {
  126. }
  127. void execute_impl(Bytecode::Interpreter&) const;
  128. String to_string_impl(Bytecode::Executable const&) const;
  129. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  130. private:
  131. StringTableIndex m_string;
  132. };
  133. class NewObject final : public Instruction {
  134. public:
  135. NewObject()
  136. : Instruction(Type::NewObject)
  137. {
  138. }
  139. void execute_impl(Bytecode::Interpreter&) const;
  140. String to_string_impl(Bytecode::Executable const&) const;
  141. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  142. };
  143. class NewRegExp final : public Instruction {
  144. public:
  145. NewRegExp(StringTableIndex source_index, StringTableIndex flags_index)
  146. : Instruction(Type::NewRegExp)
  147. , m_source_index(source_index)
  148. , m_flags_index(flags_index)
  149. {
  150. }
  151. void execute_impl(Bytecode::Interpreter&) const;
  152. String to_string_impl(Bytecode::Executable const&) const;
  153. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  154. private:
  155. StringTableIndex m_source_index;
  156. StringTableIndex m_flags_index;
  157. };
  158. // NOTE: This instruction is variable-width depending on the number of excluded names
  159. class CopyObjectExcludingProperties final : public Instruction {
  160. public:
  161. CopyObjectExcludingProperties(Register from_object, Vector<Register> const& excluded_names)
  162. : Instruction(Type::CopyObjectExcludingProperties)
  163. , m_from_object(from_object)
  164. , m_excluded_names_count(excluded_names.size())
  165. {
  166. for (size_t i = 0; i < m_excluded_names_count; i++)
  167. m_excluded_names[i] = excluded_names[i];
  168. }
  169. void execute_impl(Bytecode::Interpreter&) const;
  170. String to_string_impl(Bytecode::Executable const&) const;
  171. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  172. size_t length_impl() const { return sizeof(*this) + sizeof(Register) * m_excluded_names_count; }
  173. private:
  174. Register m_from_object;
  175. size_t m_excluded_names_count { 0 };
  176. Register m_excluded_names[];
  177. };
  178. class NewBigInt final : public Instruction {
  179. public:
  180. explicit NewBigInt(Crypto::SignedBigInteger bigint)
  181. : Instruction(Type::NewBigInt)
  182. , m_bigint(move(bigint))
  183. {
  184. }
  185. void execute_impl(Bytecode::Interpreter&) const;
  186. String to_string_impl(Bytecode::Executable const&) const;
  187. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  188. private:
  189. Crypto::SignedBigInteger m_bigint;
  190. };
  191. // NOTE: This instruction is variable-width depending on the number of elements!
  192. class NewArray final : public Instruction {
  193. public:
  194. NewArray()
  195. : Instruction(Type::NewArray)
  196. , m_element_count(0)
  197. {
  198. }
  199. explicit NewArray(Vector<Register> const& elements)
  200. : Instruction(Type::NewArray)
  201. , m_element_count(elements.size())
  202. {
  203. for (size_t i = 0; i < m_element_count; ++i)
  204. m_elements[i] = elements[i];
  205. }
  206. void execute_impl(Bytecode::Interpreter&) const;
  207. String to_string_impl(Bytecode::Executable const&) const;
  208. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  209. size_t length_impl() const
  210. {
  211. return sizeof(*this) + sizeof(Register) * m_element_count;
  212. }
  213. private:
  214. size_t m_element_count { 0 };
  215. Register m_elements[];
  216. };
  217. class IteratorToArray final : public Instruction {
  218. public:
  219. IteratorToArray()
  220. : Instruction(Type::IteratorToArray)
  221. {
  222. }
  223. void execute_impl(Bytecode::Interpreter&) const;
  224. String to_string_impl(Bytecode::Executable const&) const;
  225. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  226. };
  227. class ConcatString final : public Instruction {
  228. public:
  229. explicit ConcatString(Register lhs)
  230. : Instruction(Type::ConcatString)
  231. , m_lhs(lhs)
  232. {
  233. }
  234. void execute_impl(Bytecode::Interpreter&) const;
  235. String to_string_impl(Bytecode::Executable const&) const;
  236. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  237. private:
  238. Register m_lhs;
  239. };
  240. class SetVariable final : public Instruction {
  241. public:
  242. explicit SetVariable(IdentifierTableIndex identifier)
  243. : Instruction(Type::SetVariable)
  244. , m_identifier(identifier)
  245. {
  246. }
  247. void execute_impl(Bytecode::Interpreter&) const;
  248. String to_string_impl(Bytecode::Executable const&) const;
  249. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  250. private:
  251. IdentifierTableIndex m_identifier;
  252. };
  253. class GetVariable final : public Instruction {
  254. public:
  255. explicit GetVariable(IdentifierTableIndex identifier)
  256. : Instruction(Type::GetVariable)
  257. , m_identifier(identifier)
  258. {
  259. }
  260. void execute_impl(Bytecode::Interpreter&) const;
  261. String to_string_impl(Bytecode::Executable const&) const;
  262. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  263. private:
  264. IdentifierTableIndex m_identifier;
  265. Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate;
  266. };
  267. class GetById final : public Instruction {
  268. public:
  269. explicit GetById(IdentifierTableIndex property)
  270. : Instruction(Type::GetById)
  271. , m_property(property)
  272. {
  273. }
  274. void execute_impl(Bytecode::Interpreter&) const;
  275. String to_string_impl(Bytecode::Executable const&) const;
  276. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  277. private:
  278. IdentifierTableIndex m_property;
  279. };
  280. class PutById final : public Instruction {
  281. public:
  282. explicit PutById(Register base, IdentifierTableIndex property)
  283. : Instruction(Type::PutById)
  284. , m_base(base)
  285. , m_property(property)
  286. {
  287. }
  288. void execute_impl(Bytecode::Interpreter&) const;
  289. String to_string_impl(Bytecode::Executable const&) const;
  290. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  291. private:
  292. Register m_base;
  293. IdentifierTableIndex m_property;
  294. };
  295. class GetByValue final : public Instruction {
  296. public:
  297. explicit GetByValue(Register base)
  298. : Instruction(Type::GetByValue)
  299. , m_base(base)
  300. {
  301. }
  302. void execute_impl(Bytecode::Interpreter&) const;
  303. String to_string_impl(Bytecode::Executable const&) const;
  304. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  305. private:
  306. Register m_base;
  307. };
  308. class PutByValue final : public Instruction {
  309. public:
  310. PutByValue(Register base, Register property)
  311. : Instruction(Type::PutByValue)
  312. , m_base(base)
  313. , m_property(property)
  314. {
  315. }
  316. void execute_impl(Bytecode::Interpreter&) const;
  317. String to_string_impl(Bytecode::Executable const&) const;
  318. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  319. private:
  320. Register m_base;
  321. Register m_property;
  322. };
  323. class Jump : public Instruction {
  324. public:
  325. constexpr static bool IsTerminator = true;
  326. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  327. : Instruction(type)
  328. , m_true_target(move(taken_target))
  329. , m_false_target(move(nontaken_target))
  330. {
  331. }
  332. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  333. : Instruction(Type::Jump)
  334. , m_true_target(move(taken_target))
  335. , m_false_target(move(nontaken_target))
  336. {
  337. }
  338. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  339. {
  340. m_true_target = move(true_target);
  341. m_false_target = move(false_target);
  342. }
  343. void execute_impl(Bytecode::Interpreter&) const;
  344. String to_string_impl(Bytecode::Executable const&) const;
  345. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  346. auto& true_target() const { return m_true_target; }
  347. auto& false_target() const { return m_false_target; }
  348. protected:
  349. Optional<Label> m_true_target;
  350. Optional<Label> m_false_target;
  351. };
  352. class JumpConditional final : public Jump {
  353. public:
  354. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  355. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  356. {
  357. }
  358. void execute_impl(Bytecode::Interpreter&) const;
  359. String to_string_impl(Bytecode::Executable const&) const;
  360. };
  361. class JumpNullish final : public Jump {
  362. public:
  363. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  364. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  365. {
  366. }
  367. void execute_impl(Bytecode::Interpreter&) const;
  368. String to_string_impl(Bytecode::Executable const&) const;
  369. };
  370. class JumpUndefined final : public Jump {
  371. public:
  372. explicit JumpUndefined(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  373. : Jump(Type::JumpUndefined, move(true_target), move(false_target))
  374. {
  375. }
  376. void execute_impl(Bytecode::Interpreter&) const;
  377. String to_string_impl(Bytecode::Executable const&) const;
  378. };
  379. // NOTE: This instruction is variable-width depending on the number of arguments!
  380. class Call final : public Instruction {
  381. public:
  382. enum class CallType {
  383. Call,
  384. Construct,
  385. };
  386. Call(CallType type, Register callee, Register this_value, Vector<Register> const& arguments)
  387. : Instruction(Type::Call)
  388. , m_callee(callee)
  389. , m_this_value(this_value)
  390. , m_type(type)
  391. , m_argument_count(arguments.size())
  392. {
  393. for (size_t i = 0; i < m_argument_count; ++i)
  394. m_arguments[i] = arguments[i];
  395. }
  396. void execute_impl(Bytecode::Interpreter&) const;
  397. String to_string_impl(Bytecode::Executable const&) const;
  398. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  399. size_t length_impl() const
  400. {
  401. return sizeof(*this) + sizeof(Register) * m_argument_count;
  402. }
  403. private:
  404. Register m_callee;
  405. Register m_this_value;
  406. CallType m_type;
  407. size_t m_argument_count { 0 };
  408. Register m_arguments[];
  409. };
  410. class NewClass final : public Instruction {
  411. public:
  412. explicit NewClass(ClassExpression const& class_expression)
  413. : Instruction(Type::NewClass)
  414. , m_class_expression(class_expression)
  415. {
  416. }
  417. void execute_impl(Bytecode::Interpreter&) const;
  418. String to_string_impl(Bytecode::Executable const&) const;
  419. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  420. private:
  421. ClassExpression const& m_class_expression;
  422. };
  423. class NewFunction final : public Instruction {
  424. public:
  425. explicit NewFunction(FunctionNode const& function_node)
  426. : Instruction(Type::NewFunction)
  427. , m_function_node(function_node)
  428. {
  429. }
  430. void execute_impl(Bytecode::Interpreter&) const;
  431. String to_string_impl(Bytecode::Executable const&) const;
  432. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  433. private:
  434. FunctionNode const& m_function_node;
  435. };
  436. class Return final : public Instruction {
  437. public:
  438. constexpr static bool IsTerminator = true;
  439. Return()
  440. : Instruction(Type::Return)
  441. {
  442. }
  443. void execute_impl(Bytecode::Interpreter&) const;
  444. String to_string_impl(Bytecode::Executable const&) const;
  445. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  446. };
  447. class Increment final : public Instruction {
  448. public:
  449. Increment()
  450. : Instruction(Type::Increment)
  451. {
  452. }
  453. void execute_impl(Bytecode::Interpreter&) const;
  454. String to_string_impl(Bytecode::Executable const&) const;
  455. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  456. };
  457. class Decrement final : public Instruction {
  458. public:
  459. Decrement()
  460. : Instruction(Type::Decrement)
  461. {
  462. }
  463. void execute_impl(Bytecode::Interpreter&) const;
  464. String to_string_impl(Bytecode::Executable const&) const;
  465. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  466. };
  467. class Throw final : public Instruction {
  468. public:
  469. constexpr static bool IsTerminator = true;
  470. Throw()
  471. : Instruction(Type::Throw)
  472. {
  473. }
  474. void execute_impl(Bytecode::Interpreter&) const;
  475. String to_string_impl(Bytecode::Executable const&) const;
  476. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  477. };
  478. class EnterUnwindContext final : public Instruction {
  479. public:
  480. constexpr static bool IsTerminator = true;
  481. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  482. : Instruction(Type::EnterUnwindContext)
  483. , m_entry_point(move(entry_point))
  484. , m_handler_target(move(handler_target))
  485. , m_finalizer_target(move(finalizer_target))
  486. {
  487. }
  488. void execute_impl(Bytecode::Interpreter&) const;
  489. String to_string_impl(Bytecode::Executable const&) const;
  490. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  491. auto& entry_point() const { return m_entry_point; }
  492. auto& handler_target() const { return m_handler_target; }
  493. auto& finalizer_target() const { return m_finalizer_target; }
  494. private:
  495. Label m_entry_point;
  496. Optional<Label> m_handler_target;
  497. Optional<Label> m_finalizer_target;
  498. };
  499. class LeaveUnwindContext final : public Instruction {
  500. public:
  501. LeaveUnwindContext()
  502. : Instruction(Type::LeaveUnwindContext)
  503. {
  504. }
  505. void execute_impl(Bytecode::Interpreter&) const;
  506. String to_string_impl(Bytecode::Executable const&) const;
  507. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  508. };
  509. class FinishUnwind final : public Instruction {
  510. public:
  511. FinishUnwind(Label next)
  512. : Instruction(Type::FinishUnwind)
  513. , m_next_target(move(next))
  514. {
  515. }
  516. void execute_impl(Bytecode::Interpreter&) const;
  517. String to_string_impl(Bytecode::Executable const&) const;
  518. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  519. private:
  520. Label m_next_target;
  521. };
  522. class ContinuePendingUnwind final : public Instruction {
  523. public:
  524. constexpr static bool IsTerminator = true;
  525. explicit ContinuePendingUnwind(Label resume_target)
  526. : Instruction(Type::ContinuePendingUnwind)
  527. , m_resume_target(resume_target)
  528. {
  529. }
  530. void execute_impl(Bytecode::Interpreter&) const;
  531. String to_string_impl(Bytecode::Executable const&) const;
  532. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  533. auto& resume_target() const { return m_resume_target; }
  534. private:
  535. Label m_resume_target;
  536. };
  537. class Yield final : public Instruction {
  538. public:
  539. constexpr static bool IsTerminator = true;
  540. explicit Yield(Label continuation_label)
  541. : Instruction(Type::Yield)
  542. , m_continuation_label(continuation_label)
  543. {
  544. }
  545. explicit Yield(std::nullptr_t)
  546. : Instruction(Type::Yield)
  547. {
  548. }
  549. void execute_impl(Bytecode::Interpreter&) const;
  550. String to_string_impl(Bytecode::Executable const&) const;
  551. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  552. auto& continuation() const { return m_continuation_label; }
  553. private:
  554. Optional<Label> m_continuation_label;
  555. };
  556. class PushDeclarativeEnvironment final : public Instruction {
  557. public:
  558. explicit PushDeclarativeEnvironment(HashMap<u32, Variable> variables)
  559. : Instruction(Type::PushDeclarativeEnvironment)
  560. , m_variables(move(variables))
  561. {
  562. }
  563. void execute_impl(Bytecode::Interpreter&) const;
  564. String to_string_impl(Bytecode::Executable const&) const;
  565. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  566. private:
  567. HashMap<u32, Variable> m_variables;
  568. };
  569. class GetIterator final : public Instruction {
  570. public:
  571. GetIterator()
  572. : Instruction(Type::GetIterator)
  573. {
  574. }
  575. void execute_impl(Bytecode::Interpreter&) const;
  576. String to_string_impl(Bytecode::Executable const&) const;
  577. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  578. };
  579. class IteratorNext final : public Instruction {
  580. public:
  581. IteratorNext()
  582. : Instruction(Type::IteratorNext)
  583. {
  584. }
  585. void execute_impl(Bytecode::Interpreter&) const;
  586. String to_string_impl(Bytecode::Executable const&) const;
  587. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  588. };
  589. class IteratorResultDone final : public Instruction {
  590. public:
  591. IteratorResultDone()
  592. : Instruction(Type::IteratorResultDone)
  593. {
  594. }
  595. void execute_impl(Bytecode::Interpreter&) const;
  596. String to_string_impl(Bytecode::Executable const&) const;
  597. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  598. };
  599. class IteratorResultValue final : public Instruction {
  600. public:
  601. IteratorResultValue()
  602. : Instruction(Type::IteratorResultValue)
  603. {
  604. }
  605. void execute_impl(Bytecode::Interpreter&) const;
  606. String to_string_impl(Bytecode::Executable const&) const;
  607. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  608. };
  609. class ResolveThisBinding final : public Instruction {
  610. public:
  611. explicit ResolveThisBinding()
  612. : Instruction(Type::ResolveThisBinding)
  613. {
  614. }
  615. void execute_impl(Bytecode::Interpreter&) const;
  616. String to_string_impl(Bytecode::Executable const&) const;
  617. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  618. };
  619. }
  620. namespace JS::Bytecode {
  621. ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const
  622. {
  623. #define __BYTECODE_OP(op) \
  624. case Instruction::Type::op: \
  625. return static_cast<Bytecode::Op::op const&>(*this).execute_impl(interpreter);
  626. switch (type()) {
  627. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  628. default:
  629. VERIFY_NOT_REACHED();
  630. }
  631. #undef __BYTECODE_OP
  632. }
  633. ALWAYS_INLINE void Instruction::replace_references(BasicBlock const& from, BasicBlock const& to)
  634. {
  635. #define __BYTECODE_OP(op) \
  636. case Instruction::Type::op: \
  637. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  638. switch (type()) {
  639. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  640. default:
  641. VERIFY_NOT_REACHED();
  642. }
  643. #undef __BYTECODE_OP
  644. }
  645. ALWAYS_INLINE size_t Instruction::length() const
  646. {
  647. if (type() == Type::Call)
  648. return static_cast<Op::Call const&>(*this).length_impl();
  649. else if (type() == Type::NewArray)
  650. return static_cast<Op::NewArray const&>(*this).length_impl();
  651. else if (type() == Type::CopyObjectExcludingProperties)
  652. return static_cast<Op::CopyObjectExcludingProperties const&>(*this).length_impl();
  653. #define __BYTECODE_OP(op) \
  654. case Type::op: \
  655. return sizeof(Op::op);
  656. switch (type()) {
  657. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  658. default:
  659. VERIFY_NOT_REACHED();
  660. }
  661. #undef __BYTECODE_OP
  662. }
  663. ALWAYS_INLINE bool Instruction::is_terminator() const
  664. {
  665. #define __BYTECODE_OP(op) \
  666. case Type::op: \
  667. return Op::op::IsTerminator;
  668. switch (type()) {
  669. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  670. default:
  671. VERIFY_NOT_REACHED();
  672. }
  673. #undef __BYTECODE_OP
  674. }
  675. }