Op.h 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654
  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 GetGlobal final : public Instruction {
  448. public:
  449. explicit GetGlobal(IdentifierTableIndex identifier, u32 cache_index)
  450. : Instruction(Type::GetGlobal)
  451. , m_identifier(identifier)
  452. , m_cache_index(cache_index)
  453. {
  454. }
  455. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  456. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  457. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  458. void replace_references_impl(Register, Register) { }
  459. private:
  460. IdentifierTableIndex m_identifier;
  461. u32 m_cache_index { 0 };
  462. };
  463. class GetLocal final : public Instruction {
  464. public:
  465. explicit GetLocal(size_t index)
  466. : Instruction(Type::GetLocal)
  467. , m_index(index)
  468. {
  469. }
  470. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  471. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  472. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  473. void replace_references_impl(Register, Register) { }
  474. size_t index() const { return m_index; }
  475. private:
  476. size_t m_index;
  477. };
  478. class DeleteVariable final : public Instruction {
  479. public:
  480. explicit DeleteVariable(IdentifierTableIndex identifier)
  481. : Instruction(Type::DeleteVariable)
  482. , m_identifier(identifier)
  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. IdentifierTableIndex identifier() const { return m_identifier; }
  490. private:
  491. IdentifierTableIndex m_identifier;
  492. };
  493. class GetById final : public Instruction {
  494. public:
  495. GetById(IdentifierTableIndex property, u32 cache_index)
  496. : Instruction(Type::GetById)
  497. , m_property(property)
  498. , m_cache_index(cache_index)
  499. {
  500. }
  501. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  502. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  503. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  504. void replace_references_impl(Register, Register) { }
  505. private:
  506. IdentifierTableIndex m_property;
  507. u32 m_cache_index { 0 };
  508. };
  509. class GetByIdWithThis final : public Instruction {
  510. public:
  511. GetByIdWithThis(IdentifierTableIndex property, Register this_value, u32 cache_index)
  512. : Instruction(Type::GetByIdWithThis)
  513. , m_property(property)
  514. , m_this_value(this_value)
  515. , m_cache_index(cache_index)
  516. {
  517. }
  518. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  519. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  520. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  521. void replace_references_impl(Register from, Register to)
  522. {
  523. if (m_this_value == from)
  524. m_this_value = to;
  525. }
  526. private:
  527. IdentifierTableIndex m_property;
  528. Register m_this_value;
  529. u32 m_cache_index { 0 };
  530. };
  531. class GetPrivateById final : public Instruction {
  532. public:
  533. explicit GetPrivateById(IdentifierTableIndex property)
  534. : Instruction(Type::GetPrivateById)
  535. , m_property(property)
  536. {
  537. }
  538. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  539. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  540. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  541. void replace_references_impl(Register, Register) { }
  542. private:
  543. IdentifierTableIndex m_property;
  544. };
  545. class HasPrivateId final : public Instruction {
  546. public:
  547. explicit HasPrivateId(IdentifierTableIndex property)
  548. : Instruction(Type::HasPrivateId)
  549. , m_property(property)
  550. {
  551. }
  552. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  553. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  554. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  555. void replace_references_impl(Register, Register) { }
  556. private:
  557. IdentifierTableIndex m_property;
  558. };
  559. enum class PropertyKind {
  560. Getter,
  561. Setter,
  562. KeyValue,
  563. DirectKeyValue, // Used for Object expressions. Always sets an own property, never calls a setter.
  564. Spread,
  565. ProtoSetter,
  566. };
  567. class PutById final : public Instruction {
  568. public:
  569. explicit PutById(Register base, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  570. : Instruction(Type::PutById)
  571. , m_base(base)
  572. , m_property(property)
  573. , m_kind(kind)
  574. {
  575. }
  576. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  577. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  578. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  579. void replace_references_impl(Register from, Register to)
  580. {
  581. if (m_base == from)
  582. m_base = to;
  583. }
  584. private:
  585. Register m_base;
  586. IdentifierTableIndex m_property;
  587. PropertyKind m_kind;
  588. };
  589. class PutByIdWithThis final : public Instruction {
  590. public:
  591. PutByIdWithThis(Register base, Register this_value, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  592. : Instruction(Type::PutByIdWithThis)
  593. , m_base(base)
  594. , m_this_value(this_value)
  595. , m_property(property)
  596. , m_kind(kind)
  597. {
  598. }
  599. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  600. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  601. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  602. void replace_references_impl(Register from, Register to)
  603. {
  604. if (m_base == from)
  605. m_base = to;
  606. if (m_this_value == from)
  607. m_this_value = to;
  608. }
  609. private:
  610. Register m_base;
  611. Register m_this_value;
  612. IdentifierTableIndex m_property;
  613. PropertyKind m_kind;
  614. };
  615. class PutPrivateById final : public Instruction {
  616. public:
  617. explicit PutPrivateById(Register base, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  618. : Instruction(Type::PutPrivateById)
  619. , m_base(base)
  620. , m_property(property)
  621. , m_kind(kind)
  622. {
  623. }
  624. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  625. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  626. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  627. void replace_references_impl(Register from, Register to)
  628. {
  629. if (m_base == from)
  630. m_base = to;
  631. }
  632. private:
  633. Register m_base;
  634. IdentifierTableIndex m_property;
  635. PropertyKind m_kind;
  636. };
  637. class DeleteById final : public Instruction {
  638. public:
  639. explicit DeleteById(IdentifierTableIndex property)
  640. : Instruction(Type::DeleteById)
  641. , m_property(property)
  642. {
  643. }
  644. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  645. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  646. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  647. void replace_references_impl(Register, Register) { }
  648. private:
  649. IdentifierTableIndex m_property;
  650. };
  651. class DeleteByIdWithThis final : public Instruction {
  652. public:
  653. DeleteByIdWithThis(Register this_value, IdentifierTableIndex property)
  654. : Instruction(Type::DeleteByIdWithThis)
  655. , m_this_value(this_value)
  656. , m_property(property)
  657. {
  658. }
  659. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  660. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  661. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  662. void replace_references_impl(Register, Register) { }
  663. private:
  664. Register m_this_value;
  665. IdentifierTableIndex m_property;
  666. };
  667. class GetByValue final : public Instruction {
  668. public:
  669. explicit GetByValue(Register base)
  670. : Instruction(Type::GetByValue)
  671. , m_base(base)
  672. {
  673. }
  674. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  675. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  676. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  677. void replace_references_impl(Register from, Register to)
  678. {
  679. if (m_base == from)
  680. m_base = to;
  681. }
  682. private:
  683. Register m_base;
  684. };
  685. class GetByValueWithThis final : public Instruction {
  686. public:
  687. GetByValueWithThis(Register base, Register this_value)
  688. : Instruction(Type::GetByValueWithThis)
  689. , m_base(base)
  690. , m_this_value(this_value)
  691. {
  692. }
  693. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  694. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  695. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  696. void replace_references_impl(Register from, Register to)
  697. {
  698. if (m_base == from)
  699. m_base = to;
  700. if (m_this_value == from)
  701. m_this_value = to;
  702. }
  703. private:
  704. Register m_base;
  705. Register m_this_value;
  706. };
  707. class PutByValue final : public Instruction {
  708. public:
  709. PutByValue(Register base, Register property, PropertyKind kind = PropertyKind::KeyValue)
  710. : Instruction(Type::PutByValue)
  711. , m_base(base)
  712. , m_property(property)
  713. , m_kind(kind)
  714. {
  715. }
  716. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  717. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  718. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  719. void replace_references_impl(Register from, Register to)
  720. {
  721. if (m_base == from)
  722. m_base = to;
  723. if (m_property == from)
  724. m_property = to;
  725. }
  726. private:
  727. Register m_base;
  728. Register m_property;
  729. PropertyKind m_kind;
  730. };
  731. class PutByValueWithThis final : public Instruction {
  732. public:
  733. PutByValueWithThis(Register base, Register property, Register this_value, PropertyKind kind = PropertyKind::KeyValue)
  734. : Instruction(Type::PutByValueWithThis)
  735. , m_base(base)
  736. , m_property(property)
  737. , m_this_value(this_value)
  738. , m_kind(kind)
  739. {
  740. }
  741. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  742. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  743. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  744. void replace_references_impl(Register from, Register to)
  745. {
  746. if (m_base == from)
  747. m_base = to;
  748. if (m_property == from)
  749. m_property = to;
  750. if (m_this_value == from)
  751. m_this_value = to;
  752. }
  753. private:
  754. Register m_base;
  755. Register m_property;
  756. Register m_this_value;
  757. PropertyKind m_kind;
  758. };
  759. class DeleteByValue final : public Instruction {
  760. public:
  761. DeleteByValue(Register base)
  762. : Instruction(Type::DeleteByValue)
  763. , m_base(base)
  764. {
  765. }
  766. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  767. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  768. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  769. void replace_references_impl(Register from, Register to)
  770. {
  771. if (m_base == from)
  772. m_base = to;
  773. }
  774. private:
  775. Register m_base;
  776. };
  777. class DeleteByValueWithThis final : public Instruction {
  778. public:
  779. DeleteByValueWithThis(Register base, Register this_value)
  780. : Instruction(Type::DeleteByValueWithThis)
  781. , m_base(base)
  782. , m_this_value(this_value)
  783. {
  784. }
  785. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  786. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  787. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  788. void replace_references_impl(Register from, Register to)
  789. {
  790. if (m_base == from)
  791. m_base = to;
  792. }
  793. private:
  794. Register m_base;
  795. Register m_this_value;
  796. };
  797. class Jump : public Instruction {
  798. public:
  799. constexpr static bool IsTerminator = true;
  800. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  801. : Instruction(type)
  802. , m_true_target(move(taken_target))
  803. , m_false_target(move(nontaken_target))
  804. {
  805. }
  806. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  807. : Instruction(Type::Jump)
  808. , m_true_target(move(taken_target))
  809. , m_false_target(move(nontaken_target))
  810. {
  811. }
  812. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  813. {
  814. m_true_target = move(true_target);
  815. m_false_target = move(false_target);
  816. }
  817. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  818. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  819. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  820. void replace_references_impl(Register, Register) { }
  821. auto& true_target() const { return m_true_target; }
  822. auto& false_target() const { return m_false_target; }
  823. protected:
  824. Optional<Label> m_true_target;
  825. Optional<Label> m_false_target;
  826. };
  827. class JumpConditional final : public Jump {
  828. public:
  829. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  830. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  831. {
  832. }
  833. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  834. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  835. };
  836. class JumpNullish final : public Jump {
  837. public:
  838. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  839. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  840. {
  841. }
  842. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  843. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  844. };
  845. class JumpUndefined final : public Jump {
  846. public:
  847. explicit JumpUndefined(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  848. : Jump(Type::JumpUndefined, move(true_target), move(false_target))
  849. {
  850. }
  851. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  852. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  853. };
  854. enum class CallType {
  855. Call,
  856. Construct,
  857. DirectEval,
  858. };
  859. class Call final : public Instruction {
  860. public:
  861. Call(CallType type, Register callee, Register this_value, Register first_argument, u32 argument_count, Optional<StringTableIndex> expression_string = {})
  862. : Instruction(Type::Call)
  863. , m_callee(callee)
  864. , m_this_value(this_value)
  865. , m_first_argument(first_argument)
  866. , m_argument_count(argument_count)
  867. , m_type(type)
  868. , m_expression_string(expression_string)
  869. {
  870. }
  871. CallType call_type() const { return m_type; }
  872. Register callee() const { return m_callee; }
  873. Register this_value() const { return m_this_value; }
  874. Optional<StringTableIndex> const& expression_string() const { return m_expression_string; }
  875. Register first_argument() const { return m_first_argument; }
  876. u32 argument_count() const { return m_argument_count; }
  877. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  878. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  879. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  880. void replace_references_impl(Register, Register);
  881. private:
  882. Register m_callee;
  883. Register m_this_value;
  884. Register m_first_argument;
  885. u32 m_argument_count { 0 };
  886. CallType m_type;
  887. Optional<StringTableIndex> m_expression_string;
  888. };
  889. class CallWithArgumentArray final : public Instruction {
  890. public:
  891. CallWithArgumentArray(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})
  892. : Instruction(Type::CallWithArgumentArray)
  893. , m_callee(callee)
  894. , m_this_value(this_value)
  895. , m_type(type)
  896. , m_expression_string(expression_string)
  897. {
  898. }
  899. CallType call_type() const { return m_type; }
  900. Register callee() const { return m_callee; }
  901. Register this_value() const { return m_this_value; }
  902. Optional<StringTableIndex> const& expression_string() const { return m_expression_string; }
  903. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  904. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  905. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  906. void replace_references_impl(Register, Register);
  907. private:
  908. Register m_callee;
  909. Register m_this_value;
  910. CallType m_type;
  911. Optional<StringTableIndex> m_expression_string;
  912. };
  913. class SuperCallWithArgumentArray : public Instruction {
  914. public:
  915. explicit SuperCallWithArgumentArray(bool is_synthetic)
  916. : Instruction(Type::SuperCallWithArgumentArray)
  917. , m_is_synthetic(is_synthetic)
  918. {
  919. }
  920. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  921. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  922. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  923. void replace_references_impl(Register, Register) { }
  924. private:
  925. bool m_is_synthetic;
  926. };
  927. class NewClass final : public Instruction {
  928. public:
  929. explicit NewClass(ClassExpression const& class_expression, Optional<IdentifierTableIndex> lhs_name)
  930. : Instruction(Type::NewClass)
  931. , m_class_expression(class_expression)
  932. , m_lhs_name(lhs_name)
  933. {
  934. }
  935. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  936. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  937. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  938. void replace_references_impl(Register, Register) { }
  939. private:
  940. ClassExpression const& m_class_expression;
  941. Optional<IdentifierTableIndex> m_lhs_name;
  942. };
  943. class NewFunction final : public Instruction {
  944. public:
  945. explicit NewFunction(FunctionExpression const& function_node, Optional<IdentifierTableIndex> lhs_name, Optional<Register> home_object = {})
  946. : Instruction(Type::NewFunction)
  947. , m_function_node(function_node)
  948. , m_lhs_name(lhs_name)
  949. , m_home_object(move(home_object))
  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. FunctionExpression const& m_function_node;
  958. Optional<IdentifierTableIndex> m_lhs_name;
  959. Optional<Register> m_home_object;
  960. };
  961. class BlockDeclarationInstantiation final : public Instruction {
  962. public:
  963. explicit BlockDeclarationInstantiation(ScopeNode const& scope_node)
  964. : Instruction(Type::BlockDeclarationInstantiation)
  965. , m_scope_node(scope_node)
  966. {
  967. }
  968. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  969. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  970. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  971. void replace_references_impl(Register, Register) { }
  972. private:
  973. ScopeNode const& m_scope_node;
  974. };
  975. class Return final : public Instruction {
  976. public:
  977. constexpr static bool IsTerminator = true;
  978. Return()
  979. : Instruction(Type::Return)
  980. {
  981. }
  982. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  983. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  984. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  985. void replace_references_impl(Register, Register) { }
  986. };
  987. class Increment final : public Instruction {
  988. public:
  989. Increment()
  990. : Instruction(Type::Increment)
  991. {
  992. }
  993. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  994. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  995. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  996. void replace_references_impl(Register, Register) { }
  997. };
  998. class Decrement final : public Instruction {
  999. public:
  1000. Decrement()
  1001. : Instruction(Type::Decrement)
  1002. {
  1003. }
  1004. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1005. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1006. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1007. void replace_references_impl(Register, Register) { }
  1008. };
  1009. class ToNumeric final : public Instruction {
  1010. public:
  1011. ToNumeric()
  1012. : Instruction(Type::ToNumeric)
  1013. {
  1014. }
  1015. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1016. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1017. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1018. void replace_references_impl(Register, Register) { }
  1019. };
  1020. class Throw final : public Instruction {
  1021. public:
  1022. constexpr static bool IsTerminator = true;
  1023. Throw()
  1024. : Instruction(Type::Throw)
  1025. {
  1026. }
  1027. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1028. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1029. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1030. void replace_references_impl(Register, Register) { }
  1031. };
  1032. class ThrowIfNotObject final : public Instruction {
  1033. public:
  1034. ThrowIfNotObject()
  1035. : Instruction(Type::ThrowIfNotObject)
  1036. {
  1037. }
  1038. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1039. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1040. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1041. void replace_references_impl(Register, Register) { }
  1042. };
  1043. class ThrowIfNullish final : public Instruction {
  1044. public:
  1045. ThrowIfNullish()
  1046. : Instruction(Type::ThrowIfNullish)
  1047. {
  1048. }
  1049. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1050. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1051. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1052. void replace_references_impl(Register, Register) { }
  1053. };
  1054. class EnterUnwindContext final : public Instruction {
  1055. public:
  1056. constexpr static bool IsTerminator = true;
  1057. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  1058. : Instruction(Type::EnterUnwindContext)
  1059. , m_entry_point(move(entry_point))
  1060. , m_handler_target(move(handler_target))
  1061. , m_finalizer_target(move(finalizer_target))
  1062. {
  1063. }
  1064. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1065. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1066. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  1067. void replace_references_impl(Register, Register) { }
  1068. auto& entry_point() const { return m_entry_point; }
  1069. auto& handler_target() const { return m_handler_target; }
  1070. auto& finalizer_target() const { return m_finalizer_target; }
  1071. private:
  1072. Label m_entry_point;
  1073. Optional<Label> m_handler_target;
  1074. Optional<Label> m_finalizer_target;
  1075. };
  1076. class ScheduleJump final : public Instruction {
  1077. public:
  1078. // Note: We use this instruction to tell the next `finally` block to
  1079. // continue execution with a specific break/continue target;
  1080. // FIXME: We currently don't clear the interpreter internal flag, when we change
  1081. // the control-flow (`break`, `continue`) in a finally-block,
  1082. // FIXME: .NET on x86_64 uses a call to the finally instead, which could make this
  1083. // easier, at the cost of making control-flow changes (`break`, `continue`, `return`)
  1084. // in the finally-block more difficult, but as stated above, those
  1085. // aren't handled 100% correctly at the moment anyway
  1086. // It might be worth investigating a similar mechanism
  1087. constexpr static bool IsTerminator = true;
  1088. ScheduleJump(Label target)
  1089. : Instruction(Type::ScheduleJump)
  1090. , m_target(target)
  1091. {
  1092. }
  1093. Label target() const { return m_target; }
  1094. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1095. void replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  1096. {
  1097. if (&m_target.block() == &from)
  1098. m_target = Label { to };
  1099. }
  1100. void replace_references_impl(Register, Register) { }
  1101. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1102. private:
  1103. Label m_target;
  1104. };
  1105. class LeaveLexicalEnvironment final : public Instruction {
  1106. public:
  1107. LeaveLexicalEnvironment()
  1108. : Instruction(Type::LeaveLexicalEnvironment)
  1109. {
  1110. }
  1111. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1112. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1113. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1114. void replace_references_impl(Register, Register) { }
  1115. };
  1116. class LeaveUnwindContext final : public Instruction {
  1117. public:
  1118. LeaveUnwindContext()
  1119. : Instruction(Type::LeaveUnwindContext)
  1120. {
  1121. }
  1122. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1123. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1124. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1125. void replace_references_impl(Register, Register) { }
  1126. };
  1127. class ContinuePendingUnwind final : public Instruction {
  1128. public:
  1129. constexpr static bool IsTerminator = true;
  1130. explicit ContinuePendingUnwind(Label resume_target)
  1131. : Instruction(Type::ContinuePendingUnwind)
  1132. , m_resume_target(resume_target)
  1133. {
  1134. }
  1135. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1136. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1137. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  1138. void replace_references_impl(Register, Register) { }
  1139. auto& resume_target() const { return m_resume_target; }
  1140. private:
  1141. Label m_resume_target;
  1142. };
  1143. class Yield final : public Instruction {
  1144. public:
  1145. constexpr static bool IsTerminator = true;
  1146. explicit Yield(Label continuation_label)
  1147. : Instruction(Type::Yield)
  1148. , m_continuation_label(continuation_label)
  1149. {
  1150. }
  1151. explicit Yield(nullptr_t)
  1152. : Instruction(Type::Yield)
  1153. {
  1154. }
  1155. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1156. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1157. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  1158. void replace_references_impl(Register, Register) { }
  1159. auto& continuation() const { return m_continuation_label; }
  1160. private:
  1161. Optional<Label> m_continuation_label;
  1162. };
  1163. class PushDeclarativeEnvironment final : public Instruction {
  1164. public:
  1165. explicit PushDeclarativeEnvironment(HashMap<u32, Variable> variables)
  1166. : Instruction(Type::PushDeclarativeEnvironment)
  1167. , m_variables(move(variables))
  1168. {
  1169. }
  1170. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1171. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1172. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1173. void replace_references_impl(Register, Register) { }
  1174. private:
  1175. HashMap<u32, Variable> m_variables;
  1176. };
  1177. class GetIterator final : public Instruction {
  1178. public:
  1179. GetIterator(IteratorHint hint = IteratorHint::Sync)
  1180. : Instruction(Type::GetIterator)
  1181. , m_hint(hint)
  1182. {
  1183. }
  1184. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1185. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1186. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1187. void replace_references_impl(Register, Register) { }
  1188. private:
  1189. IteratorHint m_hint { IteratorHint::Sync };
  1190. };
  1191. class GetMethod final : public Instruction {
  1192. public:
  1193. GetMethod(IdentifierTableIndex property)
  1194. : Instruction(Type::GetMethod)
  1195. , m_property(property)
  1196. {
  1197. }
  1198. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1199. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1200. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1201. void replace_references_impl(Register, Register) { }
  1202. private:
  1203. IdentifierTableIndex m_property;
  1204. };
  1205. class GetObjectPropertyIterator final : public Instruction {
  1206. public:
  1207. GetObjectPropertyIterator()
  1208. : Instruction(Type::GetObjectPropertyIterator)
  1209. {
  1210. }
  1211. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1212. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1213. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1214. void replace_references_impl(Register, Register) { }
  1215. };
  1216. class IteratorClose final : public Instruction {
  1217. public:
  1218. IteratorClose(Completion::Type completion_type, Optional<Value> completion_value)
  1219. : Instruction(Type::IteratorClose)
  1220. , m_completion_type(completion_type)
  1221. , m_completion_value(completion_value)
  1222. {
  1223. }
  1224. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1225. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1226. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1227. void replace_references_impl(Register, Register) { }
  1228. private:
  1229. Completion::Type m_completion_type { Completion::Type::Normal };
  1230. Optional<Value> m_completion_value;
  1231. };
  1232. class IteratorNext final : public Instruction {
  1233. public:
  1234. IteratorNext()
  1235. : Instruction(Type::IteratorNext)
  1236. {
  1237. }
  1238. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1239. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1240. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1241. void replace_references_impl(Register, Register) { }
  1242. };
  1243. class IteratorResultDone final : public Instruction {
  1244. public:
  1245. IteratorResultDone()
  1246. : Instruction(Type::IteratorResultDone)
  1247. {
  1248. }
  1249. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1250. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1251. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1252. void replace_references_impl(Register, Register) { }
  1253. };
  1254. class IteratorResultValue final : public Instruction {
  1255. public:
  1256. IteratorResultValue()
  1257. : Instruction(Type::IteratorResultValue)
  1258. {
  1259. }
  1260. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1261. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1262. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1263. void replace_references_impl(Register, Register) { }
  1264. };
  1265. class ResolveThisBinding final : public Instruction {
  1266. public:
  1267. explicit ResolveThisBinding()
  1268. : Instruction(Type::ResolveThisBinding)
  1269. {
  1270. }
  1271. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1272. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1273. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1274. void replace_references_impl(Register, Register) { }
  1275. };
  1276. class ResolveSuperBase final : public Instruction {
  1277. public:
  1278. explicit ResolveSuperBase()
  1279. : Instruction(Type::ResolveSuperBase)
  1280. {
  1281. }
  1282. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1283. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1284. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1285. void replace_references_impl(Register, Register) { }
  1286. };
  1287. class GetNewTarget final : public Instruction {
  1288. public:
  1289. explicit GetNewTarget()
  1290. : Instruction(Type::GetNewTarget)
  1291. {
  1292. }
  1293. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1294. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1295. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1296. void replace_references_impl(Register, Register) { }
  1297. };
  1298. class TypeofVariable final : public Instruction {
  1299. public:
  1300. explicit TypeofVariable(IdentifierTableIndex identifier)
  1301. : Instruction(Type::TypeofVariable)
  1302. , m_identifier(identifier)
  1303. {
  1304. }
  1305. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1306. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1307. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1308. void replace_references_impl(Register, Register) { }
  1309. private:
  1310. IdentifierTableIndex m_identifier;
  1311. };
  1312. class TypeofLocal final : public Instruction {
  1313. public:
  1314. explicit TypeofLocal(size_t index)
  1315. : Instruction(Type::TypeofLocal)
  1316. , m_index(index)
  1317. {
  1318. }
  1319. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  1320. DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
  1321. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  1322. void replace_references_impl(Register, Register) { }
  1323. private:
  1324. size_t m_index;
  1325. };
  1326. }
  1327. namespace JS::Bytecode {
  1328. ALWAYS_INLINE ThrowCompletionOr<void> Instruction::execute(Bytecode::Interpreter& interpreter) const
  1329. {
  1330. #define __BYTECODE_OP(op) \
  1331. case Instruction::Type::op: \
  1332. return static_cast<Bytecode::Op::op const&>(*this).execute_impl(interpreter);
  1333. switch (type()) {
  1334. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1335. default:
  1336. VERIFY_NOT_REACHED();
  1337. }
  1338. #undef __BYTECODE_OP
  1339. }
  1340. ALWAYS_INLINE void Instruction::replace_references(BasicBlock const& from, BasicBlock const& to)
  1341. {
  1342. #define __BYTECODE_OP(op) \
  1343. case Instruction::Type::op: \
  1344. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  1345. switch (type()) {
  1346. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1347. default:
  1348. VERIFY_NOT_REACHED();
  1349. }
  1350. #undef __BYTECODE_OP
  1351. }
  1352. ALWAYS_INLINE void Instruction::replace_references(Register from, Register to)
  1353. {
  1354. #define __BYTECODE_OP(op) \
  1355. case Instruction::Type::op: \
  1356. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  1357. switch (type()) {
  1358. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1359. default:
  1360. VERIFY_NOT_REACHED();
  1361. }
  1362. #undef __BYTECODE_OP
  1363. }
  1364. ALWAYS_INLINE size_t Instruction::length() const
  1365. {
  1366. if (type() == Type::NewArray)
  1367. return round_up_to_power_of_two(static_cast<Op::NewArray const&>(*this).length_impl(), alignof(void*));
  1368. if (type() == Type::CopyObjectExcludingProperties)
  1369. return round_up_to_power_of_two(static_cast<Op::CopyObjectExcludingProperties const&>(*this).length_impl(), alignof(void*));
  1370. #define __BYTECODE_OP(op) \
  1371. case Type::op: \
  1372. return sizeof(Op::op);
  1373. switch (type()) {
  1374. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1375. default:
  1376. VERIFY_NOT_REACHED();
  1377. }
  1378. #undef __BYTECODE_OP
  1379. }
  1380. ALWAYS_INLINE bool Instruction::is_terminator() const
  1381. {
  1382. #define __BYTECODE_OP(op) \
  1383. case Type::op: \
  1384. return Op::op::IsTerminator;
  1385. switch (type()) {
  1386. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  1387. default:
  1388. VERIFY_NOT_REACHED();
  1389. }
  1390. #undef __BYTECODE_OP
  1391. }
  1392. }