Op.h 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635
  1. /*
  2. * Copyright (c) 2021-2023, 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 <AK/StdLibExtras.h>
  10. #include <LibCrypto/BigInt/SignedBigInteger.h>
  11. #include <LibJS/Bytecode/IdentifierTable.h>
  12. #include <LibJS/Bytecode/Instruction.h>
  13. #include <LibJS/Bytecode/Label.h>
  14. #include <LibJS/Bytecode/Register.h>
  15. #include <LibJS/Bytecode/StringTable.h>
  16. #include <LibJS/Heap/Cell.h>
  17. #include <LibJS/Runtime/Environment.h>
  18. #include <LibJS/Runtime/EnvironmentCoordinate.h>
  19. #include <LibJS/Runtime/IteratorOperations.h>
  20. #include <LibJS/Runtime/Value.h>
  21. #include <LibJS/Runtime/ValueTraits.h>
  22. namespace JS {
  23. class FunctionExpression;
  24. }
  25. namespace JS::Bytecode::Op {
  26. class Load final : public Instruction {
  27. public:
  28. explicit Load(Register src)
  29. : Instruction(Type::Load)
  30. , m_src(src)
  31. {
  32. }
  33. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  34. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  35. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  36. void replace_references_impl(Register from, Register to)
  37. {
  38. if (m_src == from)
  39. m_src = to;
  40. }
  41. private:
  42. Register m_src;
  43. };
  44. class LoadImmediate final : public Instruction {
  45. public:
  46. explicit LoadImmediate(Value value)
  47. : Instruction(Type::LoadImmediate)
  48. , m_value(value)
  49. {
  50. }
  51. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  52. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  53. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  54. void replace_references_impl(Register, Register) { }
  55. private:
  56. Value m_value;
  57. };
  58. class Store final : public Instruction {
  59. public:
  60. explicit Store(Register dst)
  61. : Instruction(Type::Store)
  62. , m_dst(dst)
  63. {
  64. }
  65. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  66. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  67. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  68. void replace_references_impl(Register, Register) { }
  69. Register dst() const { return m_dst; }
  70. private:
  71. Register m_dst;
  72. };
  73. #define JS_ENUMERATE_COMMON_BINARY_OPS(O) \
  74. O(Add, add) \
  75. O(Sub, sub) \
  76. O(Mul, mul) \
  77. O(Div, div) \
  78. O(Exp, exp) \
  79. O(Mod, mod) \
  80. O(In, in) \
  81. O(InstanceOf, instance_of) \
  82. O(GreaterThan, greater_than) \
  83. O(GreaterThanEquals, greater_than_equals) \
  84. O(LessThan, less_than) \
  85. O(LessThanEquals, less_than_equals) \
  86. O(LooselyInequals, abstract_inequals) \
  87. O(LooselyEquals, abstract_equals) \
  88. O(StrictlyInequals, typed_inequals) \
  89. O(StrictlyEquals, typed_equals) \
  90. O(BitwiseAnd, bitwise_and) \
  91. O(BitwiseOr, bitwise_or) \
  92. O(BitwiseXor, bitwise_xor) \
  93. O(LeftShift, left_shift) \
  94. O(RightShift, right_shift) \
  95. O(UnsignedRightShift, unsigned_right_shift)
  96. #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  97. class OpTitleCase final : public Instruction { \
  98. public: \
  99. explicit OpTitleCase(Register lhs_reg) \
  100. : Instruction(Type::OpTitleCase) \
  101. , m_lhs_reg(lhs_reg) \
  102. { \
  103. } \
  104. \
  105. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
  106. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; \
  107. void replace_references_impl(BasicBlock const&, BasicBlock const&) \
  108. { \
  109. } \
  110. void replace_references_impl(Register from, Register to) \
  111. { \
  112. if (m_lhs_reg == from) \
  113. m_lhs_reg = to; \
  114. } \
  115. \
  116. private: \
  117. Register m_lhs_reg; \
  118. };
  119. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP)
  120. #undef JS_DECLARE_COMMON_BINARY_OP
  121. #define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
  122. O(BitwiseNot, bitwise_not) \
  123. O(Not, not_) \
  124. O(UnaryPlus, unary_plus) \
  125. O(UnaryMinus, unary_minus) \
  126. O(Typeof, typeof_)
  127. #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  128. class OpTitleCase final : public Instruction { \
  129. public: \
  130. OpTitleCase() \
  131. : Instruction(Type::OpTitleCase) \
  132. { \
  133. } \
  134. \
  135. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
  136. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; \
  137. void replace_references_impl(BasicBlock const&, BasicBlock const&) \
  138. { \
  139. } \
  140. void replace_references_impl(Register, Register) \
  141. { \
  142. } \
  143. };
  144. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
  145. #undef JS_DECLARE_COMMON_UNARY_OP
  146. class NewString final : public Instruction {
  147. public:
  148. explicit NewString(StringTableIndex string)
  149. : Instruction(Type::NewString)
  150. , m_string(string)
  151. {
  152. }
  153. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  154. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  155. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  156. void replace_references_impl(Register, Register) { }
  157. private:
  158. StringTableIndex m_string;
  159. };
  160. class NewObject final : public Instruction {
  161. public:
  162. NewObject()
  163. : Instruction(Type::NewObject)
  164. {
  165. }
  166. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  167. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  168. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  169. void replace_references_impl(Register, Register) { }
  170. };
  171. class NewRegExp final : public Instruction {
  172. public:
  173. NewRegExp(StringTableIndex source_index, StringTableIndex flags_index)
  174. : Instruction(Type::NewRegExp)
  175. , m_source_index(source_index)
  176. , m_flags_index(flags_index)
  177. {
  178. }
  179. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  180. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  181. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  182. void replace_references_impl(Register, Register) { }
  183. private:
  184. StringTableIndex m_source_index;
  185. StringTableIndex m_flags_index;
  186. };
  187. #define JS_ENUMERATE_NEW_BUILTIN_ERROR_OPS(O) \
  188. O(TypeError)
  189. #define JS_DECLARE_NEW_BUILTIN_ERROR_OP(ErrorName) \
  190. class New##ErrorName final : public Instruction { \
  191. public: \
  192. explicit New##ErrorName(StringTableIndex error_string) \
  193. : Instruction(Type::New##ErrorName) \
  194. , m_error_string(error_string) \
  195. { \
  196. } \
  197. \
  198. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
  199. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const; \
  200. void replace_references_impl(BasicBlock const&, BasicBlock const&) \
  201. { \
  202. } \
  203. void replace_references_impl(Register, Register) \
  204. { \
  205. } \
  206. \
  207. private: \
  208. StringTableIndex m_error_string; \
  209. };
  210. JS_ENUMERATE_NEW_BUILTIN_ERROR_OPS(JS_DECLARE_NEW_BUILTIN_ERROR_OP)
  211. #undef JS_DECLARE_NEW_BUILTIN_ERROR_OP
  212. // NOTE: This instruction is variable-width depending on the number of excluded names
  213. class CopyObjectExcludingProperties final : public Instruction {
  214. public:
  215. CopyObjectExcludingProperties(Register from_object, Vector<Register> const& excluded_names)
  216. : Instruction(Type::CopyObjectExcludingProperties)
  217. , m_from_object(from_object)
  218. , m_excluded_names_count(excluded_names.size())
  219. {
  220. for (size_t i = 0; i < m_excluded_names_count; i++)
  221. m_excluded_names[i] = excluded_names[i];
  222. }
  223. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  224. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  225. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  226. void replace_references_impl(Register from, Register to);
  227. size_t length_impl() const { return sizeof(*this) + sizeof(Register) * m_excluded_names_count; }
  228. private:
  229. Register m_from_object;
  230. size_t m_excluded_names_count { 0 };
  231. Register m_excluded_names[];
  232. };
  233. class NewBigInt final : public Instruction {
  234. public:
  235. explicit NewBigInt(Crypto::SignedBigInteger bigint)
  236. : Instruction(Type::NewBigInt)
  237. , m_bigint(move(bigint))
  238. {
  239. }
  240. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  241. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  242. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  243. void replace_references_impl(Register, Register) { }
  244. private:
  245. Crypto::SignedBigInteger m_bigint;
  246. };
  247. // NOTE: This instruction is variable-width depending on the number of elements!
  248. class NewArray final : public Instruction {
  249. public:
  250. NewArray()
  251. : Instruction(Type::NewArray)
  252. , m_element_count(0)
  253. {
  254. }
  255. explicit NewArray(AK::Array<Register, 2> const& elements_range)
  256. : Instruction(Type::NewArray)
  257. , m_element_count(elements_range[1].index() - elements_range[0].index() + 1)
  258. {
  259. m_elements[0] = elements_range[0];
  260. m_elements[1] = elements_range[1];
  261. }
  262. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  263. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  264. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  265. // Note: The underlying element range shall never be changed item, by item
  266. // shifting it may be done in the future
  267. void replace_references_impl(Register from, Register) { VERIFY(!m_element_count || from.index() < start().index() || from.index() > end().index()); }
  268. size_t length_impl() const
  269. {
  270. return sizeof(*this) + sizeof(Register) * (m_element_count == 0 ? 0 : 2);
  271. }
  272. Register start() const
  273. {
  274. VERIFY(m_element_count);
  275. return m_elements[0];
  276. }
  277. Register end() const
  278. {
  279. VERIFY(m_element_count);
  280. return m_elements[1];
  281. }
  282. size_t element_count() const { return m_element_count; }
  283. private:
  284. size_t m_element_count { 0 };
  285. Register m_elements[];
  286. };
  287. class Append final : public Instruction {
  288. public:
  289. Append(Register lhs, bool is_spread)
  290. : Instruction(Type::Append)
  291. , m_lhs(lhs)
  292. , m_is_spread(is_spread)
  293. {
  294. }
  295. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  296. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  297. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  298. // Note: This should never do anything, the lhs should always be an array, that is currently being constructed
  299. void replace_references_impl(Register from, Register) { VERIFY(from != m_lhs); }
  300. private:
  301. Register m_lhs;
  302. bool m_is_spread = false;
  303. };
  304. class ImportCall final : public Instruction {
  305. public:
  306. ImportCall(Register specifier, Register options)
  307. : Instruction(Type::ImportCall)
  308. , m_specifier(specifier)
  309. , m_options(options)
  310. {
  311. }
  312. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  313. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  314. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  315. void replace_references_impl(Register, Register);
  316. private:
  317. Register m_specifier;
  318. Register m_options;
  319. };
  320. class IteratorToArray final : public Instruction {
  321. public:
  322. IteratorToArray()
  323. : Instruction(Type::IteratorToArray)
  324. {
  325. }
  326. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  327. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  328. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  329. void replace_references_impl(Register, Register) { }
  330. };
  331. class ConcatString final : public Instruction {
  332. public:
  333. explicit ConcatString(Register lhs)
  334. : Instruction(Type::ConcatString)
  335. , m_lhs(lhs)
  336. {
  337. }
  338. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  339. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  340. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  341. // Note: lhs should always be a string in construction, so this should never do anything
  342. void replace_references_impl(Register from, Register) { VERIFY(from != m_lhs); }
  343. private:
  344. Register m_lhs;
  345. };
  346. enum class EnvironmentMode {
  347. Lexical,
  348. Var,
  349. };
  350. class CreateLexicalEnvironment final : public Instruction {
  351. public:
  352. explicit CreateLexicalEnvironment()
  353. : Instruction(Type::CreateLexicalEnvironment)
  354. {
  355. }
  356. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  357. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  358. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  359. void replace_references_impl(Register, Register) { }
  360. };
  361. class EnterObjectEnvironment final : public Instruction {
  362. public:
  363. explicit EnterObjectEnvironment()
  364. : Instruction(Type::EnterObjectEnvironment)
  365. {
  366. }
  367. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  368. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  369. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  370. void replace_references_impl(Register, Register) { }
  371. };
  372. class CreateVariable final : public Instruction {
  373. public:
  374. explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable, bool is_global = false)
  375. : Instruction(Type::CreateVariable)
  376. , m_identifier(identifier)
  377. , m_mode(mode)
  378. , m_is_immutable(is_immutable)
  379. , m_is_global(is_global)
  380. {
  381. }
  382. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  383. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  384. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  385. void replace_references_impl(Register, Register) { }
  386. private:
  387. IdentifierTableIndex m_identifier;
  388. EnvironmentMode m_mode;
  389. bool m_is_immutable : 4 { false };
  390. bool m_is_global : 4 { false };
  391. };
  392. class SetVariable final : public Instruction {
  393. public:
  394. enum class InitializationMode {
  395. Initialize,
  396. Set,
  397. InitializeOrSet,
  398. };
  399. explicit SetVariable(IdentifierTableIndex identifier, InitializationMode initialization_mode = InitializationMode::Set, EnvironmentMode mode = EnvironmentMode::Lexical)
  400. : Instruction(Type::SetVariable)
  401. , m_identifier(identifier)
  402. , m_mode(mode)
  403. , m_initialization_mode(initialization_mode)
  404. {
  405. }
  406. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  407. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  408. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  409. void replace_references_impl(Register, Register) { }
  410. IdentifierTableIndex identifier() const { return m_identifier; }
  411. private:
  412. IdentifierTableIndex m_identifier;
  413. EnvironmentMode m_mode;
  414. InitializationMode m_initialization_mode { InitializationMode::Set };
  415. };
  416. class SetLocal final : public Instruction {
  417. public:
  418. explicit SetLocal(size_t index)
  419. : Instruction(Type::SetLocal)
  420. , m_index(index)
  421. {
  422. }
  423. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  424. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  425. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  426. void replace_references_impl(Register, Register) { }
  427. size_t index() const { return m_index; }
  428. private:
  429. size_t m_index;
  430. };
  431. class GetVariable final : public Instruction {
  432. public:
  433. explicit GetVariable(IdentifierTableIndex identifier)
  434. : Instruction(Type::GetVariable)
  435. , m_identifier(identifier)
  436. {
  437. }
  438. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  439. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  440. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  441. void replace_references_impl(Register, Register) { }
  442. IdentifierTableIndex identifier() const { return m_identifier; }
  443. private:
  444. IdentifierTableIndex m_identifier;
  445. Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate;
  446. };
  447. class GetLocal final : public Instruction {
  448. public:
  449. explicit GetLocal(size_t index)
  450. : Instruction(Type::GetLocal)
  451. , m_index(index)
  452. {
  453. }
  454. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  455. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  456. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  457. void replace_references_impl(Register, Register) { }
  458. size_t index() const { return m_index; }
  459. private:
  460. size_t m_index;
  461. };
  462. class DeleteVariable final : public Instruction {
  463. public:
  464. explicit DeleteVariable(IdentifierTableIndex identifier)
  465. : Instruction(Type::DeleteVariable)
  466. , m_identifier(identifier)
  467. {
  468. }
  469. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  470. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  471. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  472. void replace_references_impl(Register, Register) { }
  473. IdentifierTableIndex identifier() const { return m_identifier; }
  474. private:
  475. IdentifierTableIndex m_identifier;
  476. };
  477. class GetById final : public Instruction {
  478. public:
  479. GetById(IdentifierTableIndex property, u32 cache_index)
  480. : Instruction(Type::GetById)
  481. , m_property(property)
  482. , m_cache_index(cache_index)
  483. {
  484. }
  485. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  486. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  487. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  488. void replace_references_impl(Register, Register) { }
  489. private:
  490. IdentifierTableIndex m_property;
  491. u32 m_cache_index { 0 };
  492. };
  493. class GetByIdWithThis final : public Instruction {
  494. public:
  495. GetByIdWithThis(IdentifierTableIndex property, Register this_value, u32 cache_index)
  496. : Instruction(Type::GetByIdWithThis)
  497. , m_property(property)
  498. , m_this_value(this_value)
  499. , m_cache_index(cache_index)
  500. {
  501. }
  502. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  503. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  504. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  505. void replace_references_impl(Register from, Register to)
  506. {
  507. if (m_this_value == from)
  508. m_this_value = to;
  509. }
  510. private:
  511. IdentifierTableIndex m_property;
  512. Register m_this_value;
  513. u32 m_cache_index { 0 };
  514. };
  515. class GetPrivateById final : public Instruction {
  516. public:
  517. explicit GetPrivateById(IdentifierTableIndex property)
  518. : Instruction(Type::GetPrivateById)
  519. , m_property(property)
  520. {
  521. }
  522. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  523. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  524. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  525. void replace_references_impl(Register, Register) { }
  526. private:
  527. IdentifierTableIndex m_property;
  528. };
  529. class HasPrivateId final : public Instruction {
  530. public:
  531. explicit HasPrivateId(IdentifierTableIndex property)
  532. : Instruction(Type::HasPrivateId)
  533. , m_property(property)
  534. {
  535. }
  536. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  537. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  538. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  539. void replace_references_impl(Register, Register) { }
  540. private:
  541. IdentifierTableIndex m_property;
  542. };
  543. enum class PropertyKind {
  544. Getter,
  545. Setter,
  546. KeyValue,
  547. DirectKeyValue, // Used for Object expressions. Always sets an own property, never calls a setter.
  548. Spread,
  549. ProtoSetter,
  550. };
  551. class PutById final : public Instruction {
  552. public:
  553. explicit PutById(Register base, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  554. : Instruction(Type::PutById)
  555. , m_base(base)
  556. , m_property(property)
  557. , m_kind(kind)
  558. {
  559. }
  560. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  561. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  562. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  563. void replace_references_impl(Register from, Register to)
  564. {
  565. if (m_base == from)
  566. m_base = to;
  567. }
  568. private:
  569. Register m_base;
  570. IdentifierTableIndex m_property;
  571. PropertyKind m_kind;
  572. };
  573. class PutByIdWithThis final : public Instruction {
  574. public:
  575. PutByIdWithThis(Register base, Register this_value, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  576. : Instruction(Type::PutByIdWithThis)
  577. , m_base(base)
  578. , m_this_value(this_value)
  579. , m_property(property)
  580. , m_kind(kind)
  581. {
  582. }
  583. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  584. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  585. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  586. void replace_references_impl(Register from, Register to)
  587. {
  588. if (m_base == from)
  589. m_base = to;
  590. if (m_this_value == from)
  591. m_this_value = to;
  592. }
  593. private:
  594. Register m_base;
  595. Register m_this_value;
  596. IdentifierTableIndex m_property;
  597. PropertyKind m_kind;
  598. };
  599. class PutPrivateById final : public Instruction {
  600. public:
  601. explicit PutPrivateById(Register base, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  602. : Instruction(Type::PutPrivateById)
  603. , m_base(base)
  604. , m_property(property)
  605. , m_kind(kind)
  606. {
  607. }
  608. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  609. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  610. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  611. void replace_references_impl(Register from, Register to)
  612. {
  613. if (m_base == from)
  614. m_base = to;
  615. }
  616. private:
  617. Register m_base;
  618. IdentifierTableIndex m_property;
  619. PropertyKind m_kind;
  620. };
  621. class DeleteById final : public Instruction {
  622. public:
  623. explicit DeleteById(IdentifierTableIndex property)
  624. : Instruction(Type::DeleteById)
  625. , m_property(property)
  626. {
  627. }
  628. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  629. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  630. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  631. void replace_references_impl(Register, Register) { }
  632. private:
  633. IdentifierTableIndex m_property;
  634. };
  635. class DeleteByIdWithThis final : public Instruction {
  636. public:
  637. DeleteByIdWithThis(Register this_value, IdentifierTableIndex property)
  638. : Instruction(Type::DeleteByIdWithThis)
  639. , m_this_value(this_value)
  640. , m_property(property)
  641. {
  642. }
  643. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  644. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  645. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  646. void replace_references_impl(Register, Register) { }
  647. private:
  648. Register m_this_value;
  649. IdentifierTableIndex m_property;
  650. };
  651. class GetByValue final : public Instruction {
  652. public:
  653. explicit GetByValue(Register base)
  654. : Instruction(Type::GetByValue)
  655. , m_base(base)
  656. {
  657. }
  658. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  659. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  660. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  661. void replace_references_impl(Register from, Register to)
  662. {
  663. if (m_base == from)
  664. m_base = to;
  665. }
  666. private:
  667. Register m_base;
  668. };
  669. class GetByValueWithThis final : public Instruction {
  670. public:
  671. GetByValueWithThis(Register base, Register this_value)
  672. : Instruction(Type::GetByValueWithThis)
  673. , m_base(base)
  674. , m_this_value(this_value)
  675. {
  676. }
  677. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  678. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  679. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  680. void replace_references_impl(Register from, Register to)
  681. {
  682. if (m_base == from)
  683. m_base = to;
  684. if (m_this_value == from)
  685. m_this_value = to;
  686. }
  687. private:
  688. Register m_base;
  689. Register m_this_value;
  690. };
  691. class PutByValue final : public Instruction {
  692. public:
  693. PutByValue(Register base, Register property, PropertyKind kind = PropertyKind::KeyValue)
  694. : Instruction(Type::PutByValue)
  695. , m_base(base)
  696. , m_property(property)
  697. , m_kind(kind)
  698. {
  699. }
  700. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  701. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  702. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  703. void replace_references_impl(Register from, Register to)
  704. {
  705. if (m_base == from)
  706. m_base = to;
  707. if (m_property == from)
  708. m_property = to;
  709. }
  710. private:
  711. Register m_base;
  712. Register m_property;
  713. PropertyKind m_kind;
  714. };
  715. class PutByValueWithThis final : public Instruction {
  716. public:
  717. PutByValueWithThis(Register base, Register property, Register this_value, PropertyKind kind = PropertyKind::KeyValue)
  718. : Instruction(Type::PutByValueWithThis)
  719. , m_base(base)
  720. , m_property(property)
  721. , m_this_value(this_value)
  722. , m_kind(kind)
  723. {
  724. }
  725. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  726. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  727. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  728. void replace_references_impl(Register from, Register to)
  729. {
  730. if (m_base == from)
  731. m_base = to;
  732. if (m_property == from)
  733. m_property = to;
  734. if (m_this_value == from)
  735. m_this_value = to;
  736. }
  737. private:
  738. Register m_base;
  739. Register m_property;
  740. Register m_this_value;
  741. PropertyKind m_kind;
  742. };
  743. class DeleteByValue final : public Instruction {
  744. public:
  745. DeleteByValue(Register base)
  746. : Instruction(Type::DeleteByValue)
  747. , m_base(base)
  748. {
  749. }
  750. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  751. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  752. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  753. void replace_references_impl(Register from, Register to)
  754. {
  755. if (m_base == from)
  756. m_base = to;
  757. }
  758. private:
  759. Register m_base;
  760. };
  761. class DeleteByValueWithThis final : public Instruction {
  762. public:
  763. DeleteByValueWithThis(Register base, Register this_value)
  764. : Instruction(Type::DeleteByValueWithThis)
  765. , m_base(base)
  766. , m_this_value(this_value)
  767. {
  768. }
  769. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  770. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  771. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  772. void replace_references_impl(Register from, Register to)
  773. {
  774. if (m_base == from)
  775. m_base = to;
  776. }
  777. private:
  778. Register m_base;
  779. Register m_this_value;
  780. };
  781. class Jump : public Instruction {
  782. public:
  783. constexpr static bool IsTerminator = true;
  784. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  785. : Instruction(type)
  786. , m_true_target(move(taken_target))
  787. , m_false_target(move(nontaken_target))
  788. {
  789. }
  790. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  791. : Instruction(Type::Jump)
  792. , m_true_target(move(taken_target))
  793. , m_false_target(move(nontaken_target))
  794. {
  795. }
  796. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  797. {
  798. m_true_target = move(true_target);
  799. m_false_target = move(false_target);
  800. }
  801. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  802. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  803. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  804. void replace_references_impl(Register, Register) { }
  805. auto& true_target() const { return m_true_target; }
  806. auto& false_target() const { return m_false_target; }
  807. protected:
  808. Optional<Label> m_true_target;
  809. Optional<Label> m_false_target;
  810. };
  811. class JumpConditional final : public Jump {
  812. public:
  813. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  814. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  815. {
  816. }
  817. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  818. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  819. };
  820. class JumpNullish final : public Jump {
  821. public:
  822. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  823. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  824. {
  825. }
  826. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  827. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  828. };
  829. class JumpUndefined final : public Jump {
  830. public:
  831. explicit JumpUndefined(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  832. : Jump(Type::JumpUndefined, move(true_target), move(false_target))
  833. {
  834. }
  835. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  836. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  837. };
  838. enum class CallType {
  839. Call,
  840. Construct,
  841. DirectEval,
  842. };
  843. class Call final : public Instruction {
  844. public:
  845. Call(CallType type, Register callee, Register this_value, Register first_argument, u32 argument_count, Optional<StringTableIndex> expression_string = {})
  846. : Instruction(Type::Call)
  847. , m_callee(callee)
  848. , m_this_value(this_value)
  849. , m_first_argument(first_argument)
  850. , m_argument_count(argument_count)
  851. , m_type(type)
  852. , m_expression_string(expression_string)
  853. {
  854. }
  855. CallType call_type() const { return m_type; }
  856. Register callee() const { return m_callee; }
  857. Register this_value() const { return m_this_value; }
  858. Optional<StringTableIndex> const& expression_string() const { return m_expression_string; }
  859. Register first_argument() const { return m_first_argument; }
  860. u32 argument_count() const { return m_argument_count; }
  861. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  862. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  863. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  864. void replace_references_impl(Register, Register);
  865. private:
  866. Register m_callee;
  867. Register m_this_value;
  868. Register m_first_argument;
  869. u32 m_argument_count { 0 };
  870. CallType m_type;
  871. Optional<StringTableIndex> m_expression_string;
  872. };
  873. class CallWithArgumentArray final : public Instruction {
  874. public:
  875. CallWithArgumentArray(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})
  876. : Instruction(Type::CallWithArgumentArray)
  877. , m_callee(callee)
  878. , m_this_value(this_value)
  879. , m_type(type)
  880. , m_expression_string(expression_string)
  881. {
  882. }
  883. CallType call_type() const { return m_type; }
  884. Register callee() const { return m_callee; }
  885. Register this_value() const { return m_this_value; }
  886. Optional<StringTableIndex> const& expression_string() const { return m_expression_string; }
  887. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  888. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  889. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  890. void replace_references_impl(Register, Register);
  891. private:
  892. Register m_callee;
  893. Register m_this_value;
  894. CallType m_type;
  895. Optional<StringTableIndex> m_expression_string;
  896. };
  897. class SuperCallWithArgumentArray : public Instruction {
  898. public:
  899. explicit SuperCallWithArgumentArray(bool is_synthetic)
  900. : Instruction(Type::SuperCallWithArgumentArray)
  901. , m_is_synthetic(is_synthetic)
  902. {
  903. }
  904. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  905. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  906. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  907. void replace_references_impl(Register, Register) { }
  908. private:
  909. bool m_is_synthetic;
  910. };
  911. class NewClass final : public Instruction {
  912. public:
  913. explicit NewClass(ClassExpression const& class_expression, Optional<IdentifierTableIndex> lhs_name)
  914. : Instruction(Type::NewClass)
  915. , m_class_expression(class_expression)
  916. , m_lhs_name(lhs_name)
  917. {
  918. }
  919. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  920. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  921. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  922. void replace_references_impl(Register, Register) { }
  923. private:
  924. ClassExpression const& m_class_expression;
  925. Optional<IdentifierTableIndex> m_lhs_name;
  926. };
  927. class NewFunction final : public Instruction {
  928. public:
  929. explicit NewFunction(FunctionExpression const& function_node, Optional<IdentifierTableIndex> lhs_name, Optional<Register> home_object = {})
  930. : Instruction(Type::NewFunction)
  931. , m_function_node(function_node)
  932. , m_lhs_name(lhs_name)
  933. , m_home_object(move(home_object))
  934. {
  935. }
  936. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  937. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  938. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  939. void replace_references_impl(Register, Register);
  940. private:
  941. FunctionExpression const& m_function_node;
  942. Optional<IdentifierTableIndex> m_lhs_name;
  943. Optional<Register> m_home_object;
  944. };
  945. class BlockDeclarationInstantiation final : public Instruction {
  946. public:
  947. explicit BlockDeclarationInstantiation(ScopeNode const& scope_node)
  948. : Instruction(Type::BlockDeclarationInstantiation)
  949. , m_scope_node(scope_node)
  950. {
  951. }
  952. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  953. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  954. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  955. void replace_references_impl(Register, Register) { }
  956. private:
  957. ScopeNode const& m_scope_node;
  958. };
  959. class Return final : public Instruction {
  960. public:
  961. constexpr static bool IsTerminator = true;
  962. Return()
  963. : Instruction(Type::Return)
  964. {
  965. }
  966. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  967. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  968. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  969. void replace_references_impl(Register, Register) { }
  970. };
  971. class Increment final : public Instruction {
  972. public:
  973. Increment()
  974. : Instruction(Type::Increment)
  975. {
  976. }
  977. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  978. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  979. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  980. void replace_references_impl(Register, Register) { }
  981. };
  982. class Decrement final : public Instruction {
  983. public:
  984. Decrement()
  985. : Instruction(Type::Decrement)
  986. {
  987. }
  988. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  989. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  990. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  991. void replace_references_impl(Register, Register) { }
  992. };
  993. class ToNumeric final : public Instruction {
  994. public:
  995. ToNumeric()
  996. : Instruction(Type::ToNumeric)
  997. {
  998. }
  999. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1000. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1001. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1002. void replace_references_impl(Register, Register) { }
  1003. };
  1004. class Throw final : public Instruction {
  1005. public:
  1006. constexpr static bool IsTerminator = true;
  1007. Throw()
  1008. : Instruction(Type::Throw)
  1009. {
  1010. }
  1011. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1012. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1013. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1014. void replace_references_impl(Register, Register) { }
  1015. };
  1016. class ThrowIfNotObject final : public Instruction {
  1017. public:
  1018. ThrowIfNotObject()
  1019. : Instruction(Type::ThrowIfNotObject)
  1020. {
  1021. }
  1022. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1023. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1024. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1025. void replace_references_impl(Register, Register) { }
  1026. };
  1027. class ThrowIfNullish final : public Instruction {
  1028. public:
  1029. ThrowIfNullish()
  1030. : Instruction(Type::ThrowIfNullish)
  1031. {
  1032. }
  1033. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1034. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1035. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1036. void replace_references_impl(Register, Register) { }
  1037. };
  1038. class EnterUnwindContext final : public Instruction {
  1039. public:
  1040. constexpr static bool IsTerminator = true;
  1041. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  1042. : Instruction(Type::EnterUnwindContext)
  1043. , m_entry_point(move(entry_point))
  1044. , m_handler_target(move(handler_target))
  1045. , m_finalizer_target(move(finalizer_target))
  1046. {
  1047. }
  1048. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1049. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1050. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  1051. void replace_references_impl(Register, Register) { }
  1052. auto& entry_point() const { return m_entry_point; }
  1053. auto& handler_target() const { return m_handler_target; }
  1054. auto& finalizer_target() const { return m_finalizer_target; }
  1055. private:
  1056. Label m_entry_point;
  1057. Optional<Label> m_handler_target;
  1058. Optional<Label> m_finalizer_target;
  1059. };
  1060. class ScheduleJump final : public Instruction {
  1061. public:
  1062. // Note: We use this instruction to tell the next `finally` block to
  1063. // continue execution with a specific break/continue target;
  1064. // FIXME: We currently don't clear the interpreter internal flag, when we change
  1065. // the control-flow (`break`, `continue`) in a finally-block,
  1066. // FIXME: .NET on x86_64 uses a call to the finally instead, which could make this
  1067. // easier, at the cost of making control-flow changes (`break`, `continue`, `return`)
  1068. // in the finally-block more difficult, but as stated above, those
  1069. // aren't handled 100% correctly at the moment anyway
  1070. // It might be worth investigating a similar mechanism
  1071. constexpr static bool IsTerminator = true;
  1072. ScheduleJump(Label target)
  1073. : Instruction(Type::ScheduleJump)
  1074. , m_target(target)
  1075. {
  1076. }
  1077. Label target() const { return m_target; }
  1078. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1079. void replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  1080. {
  1081. if (&m_target.block() == &from)
  1082. m_target = Label { to };
  1083. }
  1084. void replace_references_impl(Register, Register) { }
  1085. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1086. private:
  1087. Label m_target;
  1088. };
  1089. class LeaveLexicalEnvironment final : public Instruction {
  1090. public:
  1091. LeaveLexicalEnvironment()
  1092. : Instruction(Type::LeaveLexicalEnvironment)
  1093. {
  1094. }
  1095. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1096. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1097. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1098. void replace_references_impl(Register, Register) { }
  1099. };
  1100. class LeaveUnwindContext final : public Instruction {
  1101. public:
  1102. LeaveUnwindContext()
  1103. : Instruction(Type::LeaveUnwindContext)
  1104. {
  1105. }
  1106. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1107. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1108. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1109. void replace_references_impl(Register, Register) { }
  1110. };
  1111. class ContinuePendingUnwind final : public Instruction {
  1112. public:
  1113. constexpr static bool IsTerminator = true;
  1114. explicit ContinuePendingUnwind(Label resume_target)
  1115. : Instruction(Type::ContinuePendingUnwind)
  1116. , m_resume_target(resume_target)
  1117. {
  1118. }
  1119. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1120. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1121. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  1122. void replace_references_impl(Register, Register) { }
  1123. auto& resume_target() const { return m_resume_target; }
  1124. private:
  1125. Label m_resume_target;
  1126. };
  1127. class Yield final : public Instruction {
  1128. public:
  1129. constexpr static bool IsTerminator = true;
  1130. explicit Yield(Label continuation_label)
  1131. : Instruction(Type::Yield)
  1132. , m_continuation_label(continuation_label)
  1133. {
  1134. }
  1135. explicit Yield(nullptr_t)
  1136. : Instruction(Type::Yield)
  1137. {
  1138. }
  1139. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1140. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1141. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  1142. void replace_references_impl(Register, Register) { }
  1143. auto& continuation() const { return m_continuation_label; }
  1144. private:
  1145. Optional<Label> m_continuation_label;
  1146. };
  1147. class PushDeclarativeEnvironment final : public Instruction {
  1148. public:
  1149. explicit PushDeclarativeEnvironment(HashMap<u32, Variable> variables)
  1150. : Instruction(Type::PushDeclarativeEnvironment)
  1151. , m_variables(move(variables))
  1152. {
  1153. }
  1154. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1155. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1156. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1157. void replace_references_impl(Register, Register) { }
  1158. private:
  1159. HashMap<u32, Variable> m_variables;
  1160. };
  1161. class GetIterator final : public Instruction {
  1162. public:
  1163. GetIterator(IteratorHint hint = IteratorHint::Sync)
  1164. : Instruction(Type::GetIterator)
  1165. , m_hint(hint)
  1166. {
  1167. }
  1168. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1169. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1170. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1171. void replace_references_impl(Register, Register) { }
  1172. private:
  1173. IteratorHint m_hint { IteratorHint::Sync };
  1174. };
  1175. class GetMethod final : public Instruction {
  1176. public:
  1177. GetMethod(IdentifierTableIndex property)
  1178. : Instruction(Type::GetMethod)
  1179. , m_property(property)
  1180. {
  1181. }
  1182. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1183. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1184. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1185. void replace_references_impl(Register, Register) { }
  1186. private:
  1187. IdentifierTableIndex m_property;
  1188. };
  1189. class GetObjectPropertyIterator final : public Instruction {
  1190. public:
  1191. GetObjectPropertyIterator()
  1192. : Instruction(Type::GetObjectPropertyIterator)
  1193. {
  1194. }
  1195. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1196. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1197. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1198. void replace_references_impl(Register, Register) { }
  1199. };
  1200. class IteratorClose final : public Instruction {
  1201. public:
  1202. IteratorClose(Completion::Type completion_type, Optional<Value> completion_value)
  1203. : Instruction(Type::IteratorClose)
  1204. , m_completion_type(completion_type)
  1205. , m_completion_value(completion_value)
  1206. {
  1207. }
  1208. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1209. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1210. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1211. void replace_references_impl(Register, Register) { }
  1212. private:
  1213. Completion::Type m_completion_type { Completion::Type::Normal };
  1214. Optional<Value> m_completion_value;
  1215. };
  1216. class IteratorNext final : public Instruction {
  1217. public:
  1218. IteratorNext()
  1219. : Instruction(Type::IteratorNext)
  1220. {
  1221. }
  1222. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1223. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1224. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1225. void replace_references_impl(Register, Register) { }
  1226. };
  1227. class IteratorResultDone final : public Instruction {
  1228. public:
  1229. IteratorResultDone()
  1230. : Instruction(Type::IteratorResultDone)
  1231. {
  1232. }
  1233. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1234. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1235. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1236. void replace_references_impl(Register, Register) { }
  1237. };
  1238. class IteratorResultValue final : public Instruction {
  1239. public:
  1240. IteratorResultValue()
  1241. : Instruction(Type::IteratorResultValue)
  1242. {
  1243. }
  1244. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1245. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1246. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1247. void replace_references_impl(Register, Register) { }
  1248. };
  1249. class ResolveThisBinding final : public Instruction {
  1250. public:
  1251. explicit ResolveThisBinding()
  1252. : Instruction(Type::ResolveThisBinding)
  1253. {
  1254. }
  1255. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1256. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1257. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1258. void replace_references_impl(Register, Register) { }
  1259. };
  1260. class ResolveSuperBase final : public Instruction {
  1261. public:
  1262. explicit ResolveSuperBase()
  1263. : Instruction(Type::ResolveSuperBase)
  1264. {
  1265. }
  1266. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1267. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1268. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1269. void replace_references_impl(Register, Register) { }
  1270. };
  1271. class GetNewTarget final : public Instruction {
  1272. public:
  1273. explicit GetNewTarget()
  1274. : Instruction(Type::GetNewTarget)
  1275. {
  1276. }
  1277. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1278. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1279. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1280. void replace_references_impl(Register, Register) { }
  1281. };
  1282. class TypeofVariable final : public Instruction {
  1283. public:
  1284. explicit TypeofVariable(IdentifierTableIndex identifier)
  1285. : Instruction(Type::TypeofVariable)
  1286. , m_identifier(identifier)
  1287. {
  1288. }
  1289. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1290. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1291. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1292. void replace_references_impl(Register, Register) { }
  1293. private:
  1294. IdentifierTableIndex m_identifier;
  1295. };
  1296. class TypeofLocal final : public Instruction {
  1297. public:
  1298. explicit TypeofLocal(size_t index)
  1299. : Instruction(Type::TypeofLocal)
  1300. , m_index(index)
  1301. {
  1302. }
  1303. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1304. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1305. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1306. void replace_references_impl(Register, Register) { }
  1307. private:
  1308. size_t m_index;
  1309. };
  1310. }
  1311. namespace JS::Bytecode {
  1312. ALWAYS_INLINE ThrowCompletionOr<void> Instruction::execute(Bytecode::Interpreter& interpreter) const
  1313. {
  1314. #define __BYTECODE_OP(op) \
  1315. case Instruction::Type::op: \
  1316. return static_cast<Bytecode::Op::op const&>(*this).execute_impl(interpreter);
  1317. switch (type()) {
  1318. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1319. default:
  1320. VERIFY_NOT_REACHED();
  1321. }
  1322. #undef __BYTECODE_OP
  1323. }
  1324. ALWAYS_INLINE void Instruction::replace_references(BasicBlock const& from, BasicBlock const& to)
  1325. {
  1326. #define __BYTECODE_OP(op) \
  1327. case Instruction::Type::op: \
  1328. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  1329. switch (type()) {
  1330. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1331. default:
  1332. VERIFY_NOT_REACHED();
  1333. }
  1334. #undef __BYTECODE_OP
  1335. }
  1336. ALWAYS_INLINE void Instruction::replace_references(Register from, Register to)
  1337. {
  1338. #define __BYTECODE_OP(op) \
  1339. case Instruction::Type::op: \
  1340. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  1341. switch (type()) {
  1342. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1343. default:
  1344. VERIFY_NOT_REACHED();
  1345. }
  1346. #undef __BYTECODE_OP
  1347. }
  1348. ALWAYS_INLINE size_t Instruction::length() const
  1349. {
  1350. if (type() == Type::NewArray)
  1351. return round_up_to_power_of_two(static_cast<Op::NewArray const&>(*this).length_impl(), alignof(void*));
  1352. if (type() == Type::CopyObjectExcludingProperties)
  1353. return round_up_to_power_of_two(static_cast<Op::CopyObjectExcludingProperties const&>(*this).length_impl(), alignof(void*));
  1354. #define __BYTECODE_OP(op) \
  1355. case Type::op: \
  1356. return sizeof(Op::op);
  1357. switch (type()) {
  1358. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1359. default:
  1360. VERIFY_NOT_REACHED();
  1361. }
  1362. #undef __BYTECODE_OP
  1363. }
  1364. ALWAYS_INLINE bool Instruction::is_terminator() const
  1365. {
  1366. #define __BYTECODE_OP(op) \
  1367. case Type::op: \
  1368. return Op::op::IsTerminator;
  1369. switch (type()) {
  1370. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1371. default:
  1372. VERIFY_NOT_REACHED();
  1373. }
  1374. #undef __BYTECODE_OP
  1375. }
  1376. }