Op.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  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/EnvironmentRecord.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. 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 NewFunction final : public Instruction {
  408. public:
  409. explicit NewFunction(FunctionNode const& function_node)
  410. : Instruction(Type::NewFunction)
  411. , m_function_node(function_node)
  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. FunctionNode const& m_function_node;
  419. };
  420. class Return final : public Instruction {
  421. public:
  422. constexpr static bool IsTerminator = true;
  423. Return()
  424. : Instruction(Type::Return)
  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. };
  431. class Increment final : public Instruction {
  432. public:
  433. Increment()
  434. : Instruction(Type::Increment)
  435. {
  436. }
  437. void execute_impl(Bytecode::Interpreter&) const;
  438. String to_string_impl(Bytecode::Executable const&) const;
  439. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  440. };
  441. class Decrement final : public Instruction {
  442. public:
  443. Decrement()
  444. : Instruction(Type::Decrement)
  445. {
  446. }
  447. void execute_impl(Bytecode::Interpreter&) const;
  448. String to_string_impl(Bytecode::Executable const&) const;
  449. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  450. };
  451. class Throw final : public Instruction {
  452. public:
  453. constexpr static bool IsTerminator = true;
  454. Throw()
  455. : Instruction(Type::Throw)
  456. {
  457. }
  458. void execute_impl(Bytecode::Interpreter&) const;
  459. String to_string_impl(Bytecode::Executable const&) const;
  460. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  461. };
  462. class EnterUnwindContext final : public Instruction {
  463. public:
  464. constexpr static bool IsTerminator = true;
  465. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  466. : Instruction(Type::EnterUnwindContext)
  467. , m_entry_point(move(entry_point))
  468. , m_handler_target(move(handler_target))
  469. , m_finalizer_target(move(finalizer_target))
  470. {
  471. }
  472. void execute_impl(Bytecode::Interpreter&) const;
  473. String to_string_impl(Bytecode::Executable const&) const;
  474. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  475. auto& entry_point() const { return m_entry_point; }
  476. auto& handler_target() const { return m_handler_target; }
  477. auto& finalizer_target() const { return m_finalizer_target; }
  478. private:
  479. Label m_entry_point;
  480. Optional<Label> m_handler_target;
  481. Optional<Label> m_finalizer_target;
  482. };
  483. class LeaveUnwindContext final : public Instruction {
  484. public:
  485. LeaveUnwindContext()
  486. : Instruction(Type::LeaveUnwindContext)
  487. {
  488. }
  489. void execute_impl(Bytecode::Interpreter&) const;
  490. String to_string_impl(Bytecode::Executable const&) const;
  491. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  492. };
  493. class ContinuePendingUnwind final : public Instruction {
  494. public:
  495. constexpr static bool IsTerminator = true;
  496. explicit ContinuePendingUnwind(Label resume_target)
  497. : Instruction(Type::ContinuePendingUnwind)
  498. , m_resume_target(resume_target)
  499. {
  500. }
  501. void execute_impl(Bytecode::Interpreter&) const;
  502. String to_string_impl(Bytecode::Executable const&) const;
  503. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  504. auto& resume_target() const { return m_resume_target; }
  505. private:
  506. Label m_resume_target;
  507. };
  508. class Yield final : public Instruction {
  509. public:
  510. constexpr static bool IsTerminator = true;
  511. explicit Yield(Label continuation_label)
  512. : Instruction(Type::Yield)
  513. , m_continuation_label(continuation_label)
  514. {
  515. }
  516. explicit Yield(std::nullptr_t)
  517. : Instruction(Type::Yield)
  518. {
  519. }
  520. void execute_impl(Bytecode::Interpreter&) const;
  521. String to_string_impl(Bytecode::Executable const&) const;
  522. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  523. auto& continuation() const { return m_continuation_label; }
  524. private:
  525. Optional<Label> m_continuation_label;
  526. };
  527. class PushDeclarativeEnvironmentRecord final : public Instruction {
  528. public:
  529. explicit PushDeclarativeEnvironmentRecord(HashMap<u32, Variable> variables)
  530. : Instruction(Type::PushDeclarativeEnvironmentRecord)
  531. , m_variables(move(variables))
  532. {
  533. }
  534. void execute_impl(Bytecode::Interpreter&) const;
  535. String to_string_impl(Bytecode::Executable const&) const;
  536. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  537. private:
  538. HashMap<u32, Variable> m_variables;
  539. };
  540. class GetIterator final : public Instruction {
  541. public:
  542. GetIterator()
  543. : Instruction(Type::GetIterator)
  544. {
  545. }
  546. void execute_impl(Bytecode::Interpreter&) const;
  547. String to_string_impl(Bytecode::Executable const&) const;
  548. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  549. };
  550. class IteratorNext final : public Instruction {
  551. public:
  552. IteratorNext()
  553. : Instruction(Type::IteratorNext)
  554. {
  555. }
  556. void execute_impl(Bytecode::Interpreter&) const;
  557. String to_string_impl(Bytecode::Executable const&) const;
  558. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  559. };
  560. class IteratorResultDone final : public Instruction {
  561. public:
  562. IteratorResultDone()
  563. : Instruction(Type::IteratorResultDone)
  564. {
  565. }
  566. void execute_impl(Bytecode::Interpreter&) const;
  567. String to_string_impl(Bytecode::Executable const&) const;
  568. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  569. };
  570. class IteratorResultValue final : public Instruction {
  571. public:
  572. IteratorResultValue()
  573. : Instruction(Type::IteratorResultValue)
  574. {
  575. }
  576. void execute_impl(Bytecode::Interpreter&) const;
  577. String to_string_impl(Bytecode::Executable const&) const;
  578. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  579. };
  580. }
  581. namespace JS::Bytecode {
  582. ALWAYS_INLINE void Instruction::execute(Bytecode::Interpreter& interpreter) const
  583. {
  584. #define __BYTECODE_OP(op) \
  585. case Instruction::Type::op: \
  586. return static_cast<Bytecode::Op::op const&>(*this).execute_impl(interpreter);
  587. switch (type()) {
  588. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  589. default:
  590. VERIFY_NOT_REACHED();
  591. }
  592. #undef __BYTECODE_OP
  593. }
  594. ALWAYS_INLINE void Instruction::replace_references(BasicBlock const& from, BasicBlock const& to)
  595. {
  596. #define __BYTECODE_OP(op) \
  597. case Instruction::Type::op: \
  598. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  599. switch (type()) {
  600. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  601. default:
  602. VERIFY_NOT_REACHED();
  603. }
  604. #undef __BYTECODE_OP
  605. }
  606. ALWAYS_INLINE size_t Instruction::length() const
  607. {
  608. if (type() == Type::Call)
  609. return static_cast<Op::Call const&>(*this).length_impl();
  610. else if (type() == Type::NewArray)
  611. return static_cast<Op::NewArray const&>(*this).length_impl();
  612. else if (type() == Type::CopyObjectExcludingProperties)
  613. return static_cast<Op::CopyObjectExcludingProperties const&>(*this).length_impl();
  614. #define __BYTECODE_OP(op) \
  615. case Type::op: \
  616. return sizeof(Op::op);
  617. switch (type()) {
  618. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  619. default:
  620. VERIFY_NOT_REACHED();
  621. }
  622. #undef __BYTECODE_OP
  623. }
  624. ALWAYS_INLINE bool Instruction::is_terminator() const
  625. {
  626. #define __BYTECODE_OP(op) \
  627. case Type::op: \
  628. return Op::op::IsTerminator;
  629. switch (type()) {
  630. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  631. default:
  632. VERIFY_NOT_REACHED();
  633. }
  634. #undef __BYTECODE_OP
  635. }
  636. }