Op.h 23 KB

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