Op.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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_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(AbstractInequals, abstract_inequals) \
  71. O(AbstractEquals, abstract_equals) \
  72. O(TypedInequals, typed_inequals) \
  73. O(TypedEquals, 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. // NOTE: This instruction is variable-width depending on the number of excluded names
  142. class CopyObjectExcludingProperties final : public Instruction {
  143. public:
  144. CopyObjectExcludingProperties(Register from_object, Vector<Register> const& excluded_names)
  145. : Instruction(Type::CopyObjectExcludingProperties)
  146. , m_from_object(from_object)
  147. , m_excluded_names_count(excluded_names.size())
  148. {
  149. for (size_t i = 0; i < m_excluded_names_count; i++)
  150. m_excluded_names[i] = excluded_names[i];
  151. }
  152. void execute_impl(Bytecode::Interpreter&) const;
  153. String to_string_impl(Bytecode::Executable const&) const;
  154. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  155. size_t length_impl() const { return sizeof(*this) + sizeof(Register) * m_excluded_names_count; }
  156. private:
  157. Register m_from_object;
  158. size_t m_excluded_names_count { 0 };
  159. Register m_excluded_names[];
  160. };
  161. class NewBigInt final : public Instruction {
  162. public:
  163. explicit NewBigInt(Crypto::SignedBigInteger bigint)
  164. : Instruction(Type::NewBigInt)
  165. , m_bigint(move(bigint))
  166. {
  167. }
  168. void execute_impl(Bytecode::Interpreter&) const;
  169. String to_string_impl(Bytecode::Executable const&) const;
  170. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  171. private:
  172. Crypto::SignedBigInteger m_bigint;
  173. };
  174. // NOTE: This instruction is variable-width depending on the number of elements!
  175. class NewArray final : public Instruction {
  176. public:
  177. NewArray()
  178. : Instruction(Type::NewArray)
  179. , m_element_count(0)
  180. {
  181. }
  182. explicit NewArray(Vector<Register> const& elements)
  183. : Instruction(Type::NewArray)
  184. , m_element_count(elements.size())
  185. {
  186. for (size_t i = 0; i < m_element_count; ++i)
  187. m_elements[i] = elements[i];
  188. }
  189. void execute_impl(Bytecode::Interpreter&) const;
  190. String to_string_impl(Bytecode::Executable const&) const;
  191. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  192. size_t length_impl() const
  193. {
  194. return sizeof(*this) + sizeof(Register) * m_element_count;
  195. }
  196. private:
  197. size_t m_element_count { 0 };
  198. Register m_elements[];
  199. };
  200. class IteratorToArray final : public Instruction {
  201. public:
  202. IteratorToArray()
  203. : Instruction(Type::IteratorToArray)
  204. {
  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. };
  210. class ConcatString final : public Instruction {
  211. public:
  212. explicit ConcatString(Register lhs)
  213. : Instruction(Type::ConcatString)
  214. , m_lhs(lhs)
  215. {
  216. }
  217. void execute_impl(Bytecode::Interpreter&) const;
  218. String to_string_impl(Bytecode::Executable const&) const;
  219. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  220. private:
  221. Register m_lhs;
  222. };
  223. class SetVariable final : public Instruction {
  224. public:
  225. explicit SetVariable(StringTableIndex identifier)
  226. : Instruction(Type::SetVariable)
  227. , m_identifier(identifier)
  228. {
  229. }
  230. void execute_impl(Bytecode::Interpreter&) const;
  231. String to_string_impl(Bytecode::Executable const&) const;
  232. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  233. private:
  234. StringTableIndex m_identifier;
  235. };
  236. class GetVariable final : public Instruction {
  237. public:
  238. explicit GetVariable(StringTableIndex identifier)
  239. : Instruction(Type::GetVariable)
  240. , m_identifier(identifier)
  241. {
  242. }
  243. void execute_impl(Bytecode::Interpreter&) const;
  244. String to_string_impl(Bytecode::Executable const&) const;
  245. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  246. private:
  247. StringTableIndex m_identifier;
  248. };
  249. class GetById final : public Instruction {
  250. public:
  251. explicit GetById(StringTableIndex property)
  252. : Instruction(Type::GetById)
  253. , m_property(property)
  254. {
  255. }
  256. void execute_impl(Bytecode::Interpreter&) const;
  257. String to_string_impl(Bytecode::Executable const&) const;
  258. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  259. private:
  260. StringTableIndex m_property;
  261. };
  262. class PutById final : public Instruction {
  263. public:
  264. explicit PutById(Register base, StringTableIndex property)
  265. : Instruction(Type::PutById)
  266. , m_base(base)
  267. , m_property(property)
  268. {
  269. }
  270. void execute_impl(Bytecode::Interpreter&) const;
  271. String to_string_impl(Bytecode::Executable const&) const;
  272. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  273. private:
  274. Register m_base;
  275. StringTableIndex m_property;
  276. };
  277. class GetByValue final : public Instruction {
  278. public:
  279. explicit GetByValue(Register base)
  280. : Instruction(Type::GetByValue)
  281. , m_base(base)
  282. {
  283. }
  284. void execute_impl(Bytecode::Interpreter&) const;
  285. String to_string_impl(Bytecode::Executable const&) const;
  286. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  287. private:
  288. Register m_base;
  289. };
  290. class PutByValue final : public Instruction {
  291. public:
  292. PutByValue(Register base, Register property)
  293. : Instruction(Type::PutByValue)
  294. , m_base(base)
  295. , m_property(property)
  296. {
  297. }
  298. void execute_impl(Bytecode::Interpreter&) const;
  299. String to_string_impl(Bytecode::Executable const&) const;
  300. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  301. private:
  302. Register m_base;
  303. Register m_property;
  304. };
  305. class Jump : public Instruction {
  306. public:
  307. constexpr static bool IsTerminator = true;
  308. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  309. : Instruction(type)
  310. , m_true_target(move(taken_target))
  311. , m_false_target(move(nontaken_target))
  312. {
  313. }
  314. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  315. : Instruction(Type::Jump)
  316. , m_true_target(move(taken_target))
  317. , m_false_target(move(nontaken_target))
  318. {
  319. }
  320. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  321. {
  322. m_true_target = move(true_target);
  323. m_false_target = move(false_target);
  324. }
  325. void execute_impl(Bytecode::Interpreter&) const;
  326. String to_string_impl(Bytecode::Executable const&) const;
  327. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  328. auto& true_target() const { return m_true_target; }
  329. auto& false_target() const { return m_false_target; }
  330. protected:
  331. Optional<Label> m_true_target;
  332. Optional<Label> m_false_target;
  333. };
  334. class JumpConditional final : public Jump {
  335. public:
  336. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  337. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  338. {
  339. }
  340. void execute_impl(Bytecode::Interpreter&) const;
  341. String to_string_impl(Bytecode::Executable const&) const;
  342. };
  343. class JumpNullish final : public Jump {
  344. public:
  345. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  346. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  347. {
  348. }
  349. void execute_impl(Bytecode::Interpreter&) const;
  350. String to_string_impl(Bytecode::Executable const&) const;
  351. };
  352. class JumpUndefined final : public Jump {
  353. public:
  354. explicit JumpUndefined(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  355. : Jump(Type::JumpUndefined, 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. // NOTE: This instruction is variable-width depending on the number of arguments!
  362. class Call final : public Instruction {
  363. public:
  364. enum class CallType {
  365. Call,
  366. Construct,
  367. };
  368. Call(CallType type, Register callee, Register this_value, Vector<Register> const& arguments)
  369. : Instruction(Type::Call)
  370. , m_callee(callee)
  371. , m_this_value(this_value)
  372. , m_type(type)
  373. , m_argument_count(arguments.size())
  374. {
  375. for (size_t i = 0; i < m_argument_count; ++i)
  376. m_arguments[i] = arguments[i];
  377. }
  378. void execute_impl(Bytecode::Interpreter&) const;
  379. String to_string_impl(Bytecode::Executable const&) const;
  380. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  381. size_t length_impl() const
  382. {
  383. return sizeof(*this) + sizeof(Register) * m_argument_count;
  384. }
  385. private:
  386. Register m_callee;
  387. Register m_this_value;
  388. CallType m_type;
  389. size_t m_argument_count { 0 };
  390. Register m_arguments[];
  391. };
  392. class NewFunction final : public Instruction {
  393. public:
  394. explicit NewFunction(FunctionNode const& function_node)
  395. : Instruction(Type::NewFunction)
  396. , m_function_node(function_node)
  397. {
  398. }
  399. void execute_impl(Bytecode::Interpreter&) const;
  400. String to_string_impl(Bytecode::Executable const&) const;
  401. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  402. private:
  403. FunctionNode const& m_function_node;
  404. };
  405. class Return final : public Instruction {
  406. public:
  407. constexpr static bool IsTerminator = true;
  408. Return()
  409. : Instruction(Type::Return)
  410. {
  411. }
  412. void execute_impl(Bytecode::Interpreter&) const;
  413. String to_string_impl(Bytecode::Executable const&) const;
  414. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  415. };
  416. class Increment final : public Instruction {
  417. public:
  418. Increment()
  419. : Instruction(Type::Increment)
  420. {
  421. }
  422. void execute_impl(Bytecode::Interpreter&) const;
  423. String to_string_impl(Bytecode::Executable const&) const;
  424. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  425. };
  426. class Decrement final : public Instruction {
  427. public:
  428. Decrement()
  429. : Instruction(Type::Decrement)
  430. {
  431. }
  432. void execute_impl(Bytecode::Interpreter&) const;
  433. String to_string_impl(Bytecode::Executable const&) const;
  434. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  435. };
  436. class Throw final : public Instruction {
  437. public:
  438. constexpr static bool IsTerminator = true;
  439. Throw()
  440. : Instruction(Type::Throw)
  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 EnterUnwindContext final : public Instruction {
  448. public:
  449. constexpr static bool IsTerminator = true;
  450. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  451. : Instruction(Type::EnterUnwindContext)
  452. , m_entry_point(move(entry_point))
  453. , m_handler_target(move(handler_target))
  454. , m_finalizer_target(move(finalizer_target))
  455. {
  456. }
  457. void execute_impl(Bytecode::Interpreter&) const;
  458. String to_string_impl(Bytecode::Executable const&) const;
  459. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  460. auto& entry_point() const { return m_entry_point; }
  461. auto& handler_target() const { return m_handler_target; }
  462. auto& finalizer_target() const { return m_finalizer_target; }
  463. private:
  464. Label m_entry_point;
  465. Optional<Label> m_handler_target;
  466. Optional<Label> m_finalizer_target;
  467. };
  468. class LeaveUnwindContext final : public Instruction {
  469. public:
  470. LeaveUnwindContext()
  471. : Instruction(Type::LeaveUnwindContext)
  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 ContinuePendingUnwind final : public Instruction {
  479. public:
  480. constexpr static bool IsTerminator = true;
  481. explicit ContinuePendingUnwind(Label resume_target)
  482. : Instruction(Type::ContinuePendingUnwind)
  483. , m_resume_target(resume_target)
  484. {
  485. }
  486. void execute_impl(Bytecode::Interpreter&) const;
  487. String to_string_impl(Bytecode::Executable const&) const;
  488. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  489. auto& resume_target() const { return m_resume_target; }
  490. private:
  491. Label m_resume_target;
  492. };
  493. class Yield final : public Instruction {
  494. public:
  495. constexpr static bool IsTerminator = true;
  496. explicit Yield(Label continuation_label)
  497. : Instruction(Type::Yield)
  498. , m_continuation_label(continuation_label)
  499. {
  500. }
  501. explicit Yield(std::nullptr_t)
  502. : Instruction(Type::Yield)
  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. auto& continuation() const { return m_continuation_label; }
  509. private:
  510. Optional<Label> m_continuation_label;
  511. };
  512. class PushLexicalEnvironment final : public Instruction {
  513. public:
  514. explicit PushLexicalEnvironment(HashMap<u32, Variable> variables)
  515. : Instruction(Type::PushLexicalEnvironment)
  516. , m_variables(move(variables))
  517. {
  518. }
  519. void execute_impl(Bytecode::Interpreter&) const;
  520. String to_string_impl(Bytecode::Executable const&) const;
  521. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  522. private:
  523. HashMap<u32, Variable> m_variables;
  524. };
  525. class LoadArgument final : public Instruction {
  526. public:
  527. explicit LoadArgument(size_t index)
  528. : Instruction(Type::LoadArgument)
  529. , m_index(index)
  530. {
  531. }
  532. void execute_impl(Bytecode::Interpreter&) const;
  533. String to_string_impl(Bytecode::Executable const&) const;
  534. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  535. private:
  536. size_t m_index { 0 };
  537. };
  538. class GetIterator final : public Instruction {
  539. public:
  540. GetIterator()
  541. : Instruction(Type::GetIterator)
  542. {
  543. }
  544. void execute_impl(Bytecode::Interpreter&) const;
  545. String to_string_impl(Bytecode::Executable const&) const;
  546. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  547. };
  548. class IteratorNext final : public Instruction {
  549. public:
  550. IteratorNext()
  551. : Instruction(Type::IteratorNext)
  552. {
  553. }
  554. void execute_impl(Bytecode::Interpreter&) const;
  555. String to_string_impl(Bytecode::Executable const&) const;
  556. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  557. };
  558. class IteratorResultDone final : public Instruction {
  559. public:
  560. IteratorResultDone()
  561. : Instruction(Type::IteratorResultDone)
  562. {
  563. }
  564. void execute_impl(Bytecode::Interpreter&) const;
  565. String to_string_impl(Bytecode::Executable const&) const;
  566. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  567. };
  568. class IteratorResultValue final : public Instruction {
  569. public:
  570. IteratorResultValue()
  571. : Instruction(Type::IteratorResultValue)
  572. {
  573. }
  574. void execute_impl(Bytecode::Interpreter&) const;
  575. String to_string_impl(Bytecode::Executable const&) const;
  576. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  577. };
  578. }
  579. namespace JS::Bytecode {
  580. ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const
  581. {
  582. #define __BYTECODE_OP(op) \
  583. case Instruction::Type::op: \
  584. return static_cast<Bytecode::Op::op const&>(*this).execute_impl(interpreter);
  585. switch (type()) {
  586. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  587. default:
  588. VERIFY_NOT_REACHED();
  589. }
  590. #undef __BYTECODE_OP
  591. }
  592. ALWAYS_INLINE void Instruction::replace_references(BasicBlock const& from, BasicBlock const& to)
  593. {
  594. #define __BYTECODE_OP(op) \
  595. case Instruction::Type::op: \
  596. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  597. switch (type()) {
  598. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  599. default:
  600. VERIFY_NOT_REACHED();
  601. }
  602. #undef __BYTECODE_OP
  603. }
  604. ALWAYS_INLINE size_t Instruction::length() const
  605. {
  606. if (type() == Type::Call)
  607. return static_cast<Op::Call const&>(*this).length_impl();
  608. else if (type() == Type::NewArray)
  609. return static_cast<Op::NewArray const&>(*this).length_impl();
  610. else if (type() == Type::CopyObjectExcludingProperties)
  611. return static_cast<Op::CopyObjectExcludingProperties const&>(*this).length_impl();
  612. #define __BYTECODE_OP(op) \
  613. case Type::op: \
  614. return sizeof(Op::op);
  615. switch (type()) {
  616. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  617. default:
  618. VERIFY_NOT_REACHED();
  619. }
  620. #undef __BYTECODE_OP
  621. }
  622. ALWAYS_INLINE bool Instruction::is_terminator() const
  623. {
  624. #define __BYTECODE_OP(op) \
  625. case Type::op: \
  626. return Op::op::IsTerminator;
  627. switch (type()) {
  628. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  629. default:
  630. VERIFY_NOT_REACHED();
  631. }
  632. #undef __BYTECODE_OP
  633. }
  634. }