Op.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  4. * Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #pragma once
  9. #include <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/Value.h>
  20. #include <LibJS/Runtime/ValueTraits.h>
  21. namespace JS::Bytecode::Op {
  22. class Load final : public Instruction {
  23. public:
  24. explicit Load(Register src)
  25. : Instruction(Type::Load)
  26. , m_src(src)
  27. {
  28. }
  29. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  30. String to_string_impl(Bytecode::Executable const&) const;
  31. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  32. void replace_references_impl(Register from, Register to)
  33. {
  34. if (m_src == from)
  35. m_src = to;
  36. }
  37. private:
  38. Register m_src;
  39. };
  40. class LoadImmediate final : public Instruction {
  41. public:
  42. explicit LoadImmediate(Value value)
  43. : Instruction(Type::LoadImmediate)
  44. , m_value(value)
  45. {
  46. }
  47. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  48. String to_string_impl(Bytecode::Executable const&) const;
  49. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  50. void replace_references_impl(Register, Register) { }
  51. private:
  52. Value m_value;
  53. };
  54. class Store final : public Instruction {
  55. public:
  56. explicit Store(Register dst)
  57. : Instruction(Type::Store)
  58. , m_dst(dst)
  59. {
  60. }
  61. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  62. String to_string_impl(Bytecode::Executable const&) const;
  63. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  64. void replace_references_impl(Register, Register) { }
  65. private:
  66. Register m_dst;
  67. };
  68. #define JS_ENUMERATE_COMMON_BINARY_OPS(O) \
  69. O(Add, add) \
  70. O(Sub, sub) \
  71. O(Mul, mul) \
  72. O(Div, div) \
  73. O(Exp, exp) \
  74. O(Mod, mod) \
  75. O(In, in) \
  76. O(InstanceOf, instance_of) \
  77. O(GreaterThan, greater_than) \
  78. O(GreaterThanEquals, greater_than_equals) \
  79. O(LessThan, less_than) \
  80. O(LessThanEquals, less_than_equals) \
  81. O(LooselyInequals, abstract_inequals) \
  82. O(LooselyEquals, abstract_equals) \
  83. O(StrictlyInequals, typed_inequals) \
  84. O(StrictlyEquals, typed_equals) \
  85. O(BitwiseAnd, bitwise_and) \
  86. O(BitwiseOr, bitwise_or) \
  87. O(BitwiseXor, bitwise_xor) \
  88. O(LeftShift, left_shift) \
  89. O(RightShift, right_shift) \
  90. O(UnsignedRightShift, unsigned_right_shift)
  91. #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  92. class OpTitleCase final : public Instruction { \
  93. public: \
  94. explicit OpTitleCase(Register lhs_reg) \
  95. : Instruction(Type::OpTitleCase) \
  96. , m_lhs_reg(lhs_reg) \
  97. { \
  98. } \
  99. \
  100. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
  101. String to_string_impl(Bytecode::Executable const&) const; \
  102. void replace_references_impl(BasicBlock const&, BasicBlock const&) { } \
  103. void replace_references_impl(Register from, Register to) \
  104. { \
  105. if (m_lhs_reg == from) \
  106. m_lhs_reg = to; \
  107. } \
  108. \
  109. private: \
  110. Register m_lhs_reg; \
  111. };
  112. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP)
  113. #undef JS_DECLARE_COMMON_BINARY_OP
  114. #define JS_ENUMERATE_COMMON_UNARY_OPS(O) \
  115. O(BitwiseNot, bitwise_not) \
  116. O(Not, not_) \
  117. O(UnaryPlus, unary_plus) \
  118. O(UnaryMinus, unary_minus) \
  119. O(Typeof, typeof_)
  120. #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  121. class OpTitleCase final : public Instruction { \
  122. public: \
  123. OpTitleCase() \
  124. : Instruction(Type::OpTitleCase) \
  125. { \
  126. } \
  127. \
  128. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const; \
  129. String to_string_impl(Bytecode::Executable const&) const; \
  130. void replace_references_impl(BasicBlock const&, BasicBlock const&) { } \
  131. void replace_references_impl(Register, Register) { } \
  132. };
  133. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP)
  134. #undef JS_DECLARE_COMMON_UNARY_OP
  135. class NewString final : public Instruction {
  136. public:
  137. explicit NewString(StringTableIndex string)
  138. : Instruction(Type::NewString)
  139. , m_string(string)
  140. {
  141. }
  142. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  143. String to_string_impl(Bytecode::Executable const&) const;
  144. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  145. void replace_references_impl(Register, Register) { }
  146. private:
  147. StringTableIndex m_string;
  148. };
  149. class NewObject final : public Instruction {
  150. public:
  151. NewObject()
  152. : Instruction(Type::NewObject)
  153. {
  154. }
  155. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  156. String to_string_impl(Bytecode::Executable const&) const;
  157. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  158. void replace_references_impl(Register, Register) { }
  159. };
  160. class NewRegExp final : public Instruction {
  161. public:
  162. NewRegExp(StringTableIndex source_index, StringTableIndex flags_index)
  163. : Instruction(Type::NewRegExp)
  164. , m_source_index(source_index)
  165. , m_flags_index(flags_index)
  166. {
  167. }
  168. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  169. String to_string_impl(Bytecode::Executable const&) const;
  170. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  171. void replace_references_impl(Register, Register) { }
  172. private:
  173. StringTableIndex m_source_index;
  174. StringTableIndex m_flags_index;
  175. };
  176. // NOTE: This instruction is variable-width depending on the number of excluded names
  177. class CopyObjectExcludingProperties final : public Instruction {
  178. public:
  179. CopyObjectExcludingProperties(Register from_object, Vector<Register> const& excluded_names)
  180. : Instruction(Type::CopyObjectExcludingProperties)
  181. , m_from_object(from_object)
  182. , m_excluded_names_count(excluded_names.size())
  183. {
  184. for (size_t i = 0; i < m_excluded_names_count; i++)
  185. m_excluded_names[i] = excluded_names[i];
  186. }
  187. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  188. String to_string_impl(Bytecode::Executable const&) const;
  189. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  190. void replace_references_impl(Register from, Register to);
  191. size_t length_impl() const { return sizeof(*this) + sizeof(Register) * m_excluded_names_count; }
  192. private:
  193. Register m_from_object;
  194. size_t m_excluded_names_count { 0 };
  195. Register m_excluded_names[];
  196. };
  197. class NewBigInt final : public Instruction {
  198. public:
  199. explicit NewBigInt(Crypto::SignedBigInteger bigint)
  200. : Instruction(Type::NewBigInt)
  201. , m_bigint(move(bigint))
  202. {
  203. }
  204. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  205. String to_string_impl(Bytecode::Executable const&) const;
  206. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  207. void replace_references_impl(Register, Register) { }
  208. private:
  209. Crypto::SignedBigInteger m_bigint;
  210. };
  211. // NOTE: This instruction is variable-width depending on the number of elements!
  212. class NewArray final : public Instruction {
  213. public:
  214. NewArray()
  215. : Instruction(Type::NewArray)
  216. , m_element_count(0)
  217. {
  218. }
  219. explicit NewArray(AK::Array<Register, 2> const& elements_range)
  220. : Instruction(Type::NewArray)
  221. , m_element_count(elements_range[1].index() - elements_range[0].index() + 1)
  222. {
  223. m_elements[0] = elements_range[0];
  224. m_elements[1] = elements_range[1];
  225. }
  226. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  227. String to_string_impl(Bytecode::Executable const&) const;
  228. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  229. // Note: The underlying element range shall never be changed item, by item
  230. // shifting it may be done in the future
  231. void replace_references_impl(Register from, Register) { VERIFY(!m_element_count || from.index() < start().index() || from.index() > end().index()); }
  232. size_t length_impl() const
  233. {
  234. return sizeof(*this) + sizeof(Register) * (m_element_count == 0 ? 0 : 2);
  235. }
  236. private:
  237. size_t m_element_count { 0 };
  238. Register m_elements[];
  239. };
  240. class Append final : public Instruction {
  241. public:
  242. Append(Register lhs, bool is_spread)
  243. : Instruction(Type::Append)
  244. , m_lhs(lhs)
  245. , m_is_spread(is_spread)
  246. {
  247. }
  248. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  249. String to_string_impl(Bytecode::Executable const&) const;
  250. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  251. // Note: This should never do anything, the lhs should always be an array, that is currently being constructed
  252. void replace_references_impl(Register from, Register) { VERIFY(from != m_lhs); }
  253. private:
  254. Register m_lhs;
  255. bool m_is_spread = false;
  256. };
  257. class IteratorToArray final : public Instruction {
  258. public:
  259. IteratorToArray()
  260. : Instruction(Type::IteratorToArray)
  261. {
  262. }
  263. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  264. String to_string_impl(Bytecode::Executable const&) const;
  265. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  266. void replace_references_impl(Register, Register) { }
  267. };
  268. class ConcatString final : public Instruction {
  269. public:
  270. explicit ConcatString(Register lhs)
  271. : Instruction(Type::ConcatString)
  272. , m_lhs(lhs)
  273. {
  274. }
  275. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  276. String to_string_impl(Bytecode::Executable const&) const;
  277. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  278. // Note: lhs should always be a string in construction, so this should never do anything
  279. void replace_references_impl(Register from, Register) { VERIFY(from != m_lhs); }
  280. private:
  281. Register m_lhs;
  282. };
  283. enum class EnvironmentMode {
  284. Lexical,
  285. Var,
  286. };
  287. class CreateEnvironment final : public Instruction {
  288. public:
  289. explicit CreateEnvironment(EnvironmentMode mode)
  290. : Instruction(Type::CreateEnvironment)
  291. , m_mode(mode)
  292. {
  293. }
  294. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  295. String to_string_impl(Bytecode::Executable const&) const;
  296. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  297. void replace_references_impl(Register, Register) { }
  298. private:
  299. EnvironmentMode m_mode { EnvironmentMode::Lexical };
  300. };
  301. class EnterObjectEnvironment final : public Instruction {
  302. public:
  303. explicit EnterObjectEnvironment()
  304. : Instruction(Type::EnterObjectEnvironment)
  305. {
  306. }
  307. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  308. String to_string_impl(Bytecode::Executable const&) const;
  309. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  310. void replace_references_impl(Register, Register) { }
  311. };
  312. class CreateVariable final : public Instruction {
  313. public:
  314. explicit CreateVariable(IdentifierTableIndex identifier, EnvironmentMode mode, bool is_immutable, bool is_global = false)
  315. : Instruction(Type::CreateVariable)
  316. , m_identifier(identifier)
  317. , m_mode(mode)
  318. , m_is_immutable(is_immutable)
  319. , m_is_global(is_global)
  320. {
  321. }
  322. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  323. String to_string_impl(Bytecode::Executable const&) const;
  324. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  325. void replace_references_impl(Register, Register) { }
  326. private:
  327. IdentifierTableIndex m_identifier;
  328. EnvironmentMode m_mode;
  329. bool m_is_immutable : 4 { false };
  330. bool m_is_global : 4 { false };
  331. };
  332. class SetVariable final : public Instruction {
  333. public:
  334. enum class InitializationMode {
  335. Initialize,
  336. Set,
  337. InitializeOrSet,
  338. };
  339. explicit SetVariable(IdentifierTableIndex identifier, InitializationMode initialization_mode = InitializationMode::Set, EnvironmentMode mode = EnvironmentMode::Lexical)
  340. : Instruction(Type::SetVariable)
  341. , m_identifier(identifier)
  342. , m_mode(mode)
  343. , m_initialization_mode(initialization_mode)
  344. {
  345. }
  346. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  347. String to_string_impl(Bytecode::Executable const&) const;
  348. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  349. void replace_references_impl(Register, Register) { }
  350. private:
  351. IdentifierTableIndex m_identifier;
  352. EnvironmentMode m_mode;
  353. InitializationMode m_initialization_mode { InitializationMode::Set };
  354. };
  355. class GetVariable final : public Instruction {
  356. public:
  357. explicit GetVariable(IdentifierTableIndex identifier)
  358. : Instruction(Type::GetVariable)
  359. , m_identifier(identifier)
  360. {
  361. }
  362. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  363. String to_string_impl(Bytecode::Executable const&) const;
  364. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  365. void replace_references_impl(Register, Register) { }
  366. private:
  367. IdentifierTableIndex m_identifier;
  368. Optional<EnvironmentCoordinate> mutable m_cached_environment_coordinate;
  369. };
  370. class DeleteVariable final : public Instruction {
  371. public:
  372. explicit DeleteVariable(IdentifierTableIndex identifier)
  373. : Instruction(Type::DeleteVariable)
  374. , m_identifier(identifier)
  375. {
  376. }
  377. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  378. String to_string_impl(Bytecode::Executable const&) const;
  379. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  380. void replace_references_impl(Register, Register) { }
  381. private:
  382. IdentifierTableIndex m_identifier;
  383. };
  384. class GetById final : public Instruction {
  385. public:
  386. explicit GetById(IdentifierTableIndex property)
  387. : Instruction(Type::GetById)
  388. , m_property(property)
  389. {
  390. }
  391. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  392. String to_string_impl(Bytecode::Executable const&) const;
  393. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  394. void replace_references_impl(Register, Register) { }
  395. private:
  396. IdentifierTableIndex m_property;
  397. };
  398. enum class PropertyKind {
  399. Getter,
  400. Setter,
  401. KeyValue,
  402. Spread,
  403. ProtoSetter,
  404. };
  405. class PutById final : public Instruction {
  406. public:
  407. explicit PutById(Register base, IdentifierTableIndex property, PropertyKind kind = PropertyKind::KeyValue)
  408. : Instruction(Type::PutById)
  409. , m_base(base)
  410. , m_property(property)
  411. , m_kind(kind)
  412. {
  413. }
  414. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  415. String to_string_impl(Bytecode::Executable const&) const;
  416. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  417. void replace_references_impl(Register from, Register to)
  418. {
  419. if (m_base == from)
  420. m_base = to;
  421. }
  422. private:
  423. Register m_base;
  424. IdentifierTableIndex m_property;
  425. PropertyKind m_kind;
  426. };
  427. class DeleteById final : public Instruction {
  428. public:
  429. explicit DeleteById(IdentifierTableIndex property)
  430. : Instruction(Type::DeleteById)
  431. , m_property(property)
  432. {
  433. }
  434. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  435. String to_string_impl(Bytecode::Executable const&) const;
  436. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  437. void replace_references_impl(Register, Register) { }
  438. private:
  439. IdentifierTableIndex m_property;
  440. };
  441. class GetByValue final : public Instruction {
  442. public:
  443. explicit GetByValue(Register base)
  444. : Instruction(Type::GetByValue)
  445. , m_base(base)
  446. {
  447. }
  448. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  449. String to_string_impl(Bytecode::Executable const&) const;
  450. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  451. void replace_references_impl(Register from, Register to)
  452. {
  453. if (m_base == from)
  454. m_base = to;
  455. }
  456. private:
  457. Register m_base;
  458. };
  459. class PutByValue final : public Instruction {
  460. public:
  461. PutByValue(Register base, Register property, PropertyKind kind = PropertyKind::KeyValue)
  462. : Instruction(Type::PutByValue)
  463. , m_base(base)
  464. , m_property(property)
  465. , m_kind(kind)
  466. {
  467. }
  468. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  469. String to_string_impl(Bytecode::Executable const&) const;
  470. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  471. void replace_references_impl(Register from, Register to)
  472. {
  473. if (m_base == from)
  474. m_base = to;
  475. }
  476. private:
  477. Register m_base;
  478. Register m_property;
  479. PropertyKind m_kind;
  480. };
  481. class DeleteByValue final : public Instruction {
  482. public:
  483. DeleteByValue(Register base)
  484. : Instruction(Type::DeleteByValue)
  485. , m_base(base)
  486. {
  487. }
  488. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  489. String to_string_impl(Bytecode::Executable const&) const;
  490. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  491. void replace_references_impl(Register from, Register to)
  492. {
  493. if (m_base == from)
  494. m_base = to;
  495. }
  496. private:
  497. Register m_base;
  498. };
  499. class Jump : public Instruction {
  500. public:
  501. constexpr static bool IsTerminator = true;
  502. explicit Jump(Type type, Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  503. : Instruction(type)
  504. , m_true_target(move(taken_target))
  505. , m_false_target(move(nontaken_target))
  506. {
  507. }
  508. explicit Jump(Optional<Label> taken_target = {}, Optional<Label> nontaken_target = {})
  509. : Instruction(Type::Jump)
  510. , m_true_target(move(taken_target))
  511. , m_false_target(move(nontaken_target))
  512. {
  513. }
  514. void set_targets(Optional<Label> true_target, Optional<Label> false_target)
  515. {
  516. m_true_target = move(true_target);
  517. m_false_target = move(false_target);
  518. }
  519. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  520. String to_string_impl(Bytecode::Executable const&) const;
  521. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  522. void replace_references_impl(Register, Register) { }
  523. auto& true_target() const { return m_true_target; }
  524. auto& false_target() const { return m_false_target; }
  525. protected:
  526. Optional<Label> m_true_target;
  527. Optional<Label> m_false_target;
  528. };
  529. class JumpConditional final : public Jump {
  530. public:
  531. explicit JumpConditional(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  532. : Jump(Type::JumpConditional, move(true_target), move(false_target))
  533. {
  534. }
  535. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  536. String to_string_impl(Bytecode::Executable const&) const;
  537. };
  538. class JumpNullish final : public Jump {
  539. public:
  540. explicit JumpNullish(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  541. : Jump(Type::JumpNullish, move(true_target), move(false_target))
  542. {
  543. }
  544. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  545. String to_string_impl(Bytecode::Executable const&) const;
  546. };
  547. class JumpUndefined final : public Jump {
  548. public:
  549. explicit JumpUndefined(Optional<Label> true_target = {}, Optional<Label> false_target = {})
  550. : Jump(Type::JumpUndefined, move(true_target), move(false_target))
  551. {
  552. }
  553. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  554. String to_string_impl(Bytecode::Executable const&) const;
  555. };
  556. // NOTE: This instruction is variable-width depending on the number of arguments!
  557. class Call final : public Instruction {
  558. public:
  559. enum class CallType {
  560. Call,
  561. Construct,
  562. };
  563. Call(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})
  564. : Instruction(Type::Call)
  565. , m_callee(callee)
  566. , m_this_value(this_value)
  567. , m_type(type)
  568. , m_expression_string(expression_string)
  569. {
  570. }
  571. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  572. String to_string_impl(Bytecode::Executable const&) const;
  573. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  574. void replace_references_impl(Register, Register);
  575. Completion throw_type_error_for_callee(Bytecode::Interpreter&, StringView callee_type) const;
  576. private:
  577. Register m_callee;
  578. Register m_this_value;
  579. CallType m_type;
  580. Optional<StringTableIndex> m_expression_string;
  581. };
  582. // NOTE: This instruction is variable-width depending on the number of arguments!
  583. class SuperCall : public Instruction {
  584. public:
  585. explicit SuperCall(bool is_synthetic)
  586. : Instruction(Type::SuperCall)
  587. , m_is_synthetic(is_synthetic)
  588. {
  589. }
  590. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  591. String to_string_impl(Bytecode::Executable const&) const;
  592. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  593. void replace_references_impl(Register, Register) { }
  594. private:
  595. bool m_is_synthetic;
  596. };
  597. class NewClass final : public Instruction {
  598. public:
  599. explicit NewClass(ClassExpression const& class_expression)
  600. : Instruction(Type::NewClass)
  601. , m_class_expression(class_expression)
  602. {
  603. }
  604. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  605. String to_string_impl(Bytecode::Executable const&) const;
  606. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  607. void replace_references_impl(Register, Register) { }
  608. private:
  609. ClassExpression const& m_class_expression;
  610. };
  611. class NewFunction final : public Instruction {
  612. public:
  613. explicit NewFunction(FunctionNode const& function_node)
  614. : Instruction(Type::NewFunction)
  615. , m_function_node(function_node)
  616. {
  617. }
  618. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  619. String to_string_impl(Bytecode::Executable const&) const;
  620. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  621. void replace_references_impl(Register, Register) { }
  622. private:
  623. FunctionNode const& m_function_node;
  624. };
  625. class Return final : public Instruction {
  626. public:
  627. constexpr static bool IsTerminator = true;
  628. Return()
  629. : Instruction(Type::Return)
  630. {
  631. }
  632. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  633. String to_string_impl(Bytecode::Executable const&) const;
  634. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  635. void replace_references_impl(Register, Register) { }
  636. };
  637. class Increment final : public Instruction {
  638. public:
  639. Increment()
  640. : Instruction(Type::Increment)
  641. {
  642. }
  643. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  644. String to_string_impl(Bytecode::Executable const&) const;
  645. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  646. void replace_references_impl(Register, Register) { }
  647. };
  648. class Decrement final : public Instruction {
  649. public:
  650. Decrement()
  651. : Instruction(Type::Decrement)
  652. {
  653. }
  654. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  655. String to_string_impl(Bytecode::Executable const&) const;
  656. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  657. void replace_references_impl(Register, Register) { }
  658. };
  659. class Throw final : public Instruction {
  660. public:
  661. constexpr static bool IsTerminator = true;
  662. Throw()
  663. : Instruction(Type::Throw)
  664. {
  665. }
  666. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  667. String to_string_impl(Bytecode::Executable const&) const;
  668. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  669. void replace_references_impl(Register, Register) { }
  670. };
  671. class EnterUnwindContext final : public Instruction {
  672. public:
  673. constexpr static bool IsTerminator = true;
  674. EnterUnwindContext(Label entry_point, Optional<Label> handler_target, Optional<Label> finalizer_target)
  675. : Instruction(Type::EnterUnwindContext)
  676. , m_entry_point(move(entry_point))
  677. , m_handler_target(move(handler_target))
  678. , m_finalizer_target(move(finalizer_target))
  679. {
  680. }
  681. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  682. String to_string_impl(Bytecode::Executable const&) const;
  683. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  684. void replace_references_impl(Register, Register) { }
  685. auto& entry_point() const { return m_entry_point; }
  686. auto& handler_target() const { return m_handler_target; }
  687. auto& finalizer_target() const { return m_finalizer_target; }
  688. private:
  689. Label m_entry_point;
  690. Optional<Label> m_handler_target;
  691. Optional<Label> m_finalizer_target;
  692. };
  693. class LeaveEnvironment final : public Instruction {
  694. public:
  695. LeaveEnvironment(EnvironmentMode mode)
  696. : Instruction(Type::LeaveEnvironment)
  697. , m_mode(mode)
  698. {
  699. }
  700. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  701. String to_string_impl(Bytecode::Executable const&) const;
  702. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  703. void replace_references_impl(Register, Register) { }
  704. private:
  705. EnvironmentMode m_mode { EnvironmentMode::Lexical };
  706. };
  707. class LeaveUnwindContext final : public Instruction {
  708. public:
  709. LeaveUnwindContext()
  710. : Instruction(Type::LeaveUnwindContext)
  711. {
  712. }
  713. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  714. String to_string_impl(Bytecode::Executable const&) const;
  715. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  716. void replace_references_impl(Register, Register) { }
  717. };
  718. class FinishUnwind final : public Instruction {
  719. public:
  720. constexpr static bool IsTerminator = true;
  721. FinishUnwind(Label next)
  722. : Instruction(Type::FinishUnwind)
  723. , m_next_target(move(next))
  724. {
  725. }
  726. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  727. String to_string_impl(Bytecode::Executable const&) const;
  728. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  729. void replace_references_impl(Register, Register) { }
  730. Label next_target() const { return m_next_target; }
  731. private:
  732. Label m_next_target;
  733. };
  734. class ContinuePendingUnwind final : public Instruction {
  735. public:
  736. constexpr static bool IsTerminator = true;
  737. explicit ContinuePendingUnwind(Label resume_target)
  738. : Instruction(Type::ContinuePendingUnwind)
  739. , m_resume_target(resume_target)
  740. {
  741. }
  742. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  743. String to_string_impl(Bytecode::Executable const&) const;
  744. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  745. void replace_references_impl(Register, Register) { }
  746. auto& resume_target() const { return m_resume_target; }
  747. private:
  748. Label m_resume_target;
  749. };
  750. class Yield final : public Instruction {
  751. public:
  752. constexpr static bool IsTerminator = true;
  753. explicit Yield(Label continuation_label)
  754. : Instruction(Type::Yield)
  755. , m_continuation_label(continuation_label)
  756. {
  757. }
  758. explicit Yield(std::nullptr_t)
  759. : Instruction(Type::Yield)
  760. {
  761. }
  762. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  763. String to_string_impl(Bytecode::Executable const&) const;
  764. void replace_references_impl(BasicBlock const&, BasicBlock const&);
  765. void replace_references_impl(Register, Register) { }
  766. auto& continuation() const { return m_continuation_label; }
  767. private:
  768. Optional<Label> m_continuation_label;
  769. };
  770. class PushDeclarativeEnvironment final : public Instruction {
  771. public:
  772. explicit PushDeclarativeEnvironment(HashMap<u32, Variable> variables)
  773. : Instruction(Type::PushDeclarativeEnvironment)
  774. , m_variables(move(variables))
  775. {
  776. }
  777. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  778. String to_string_impl(Bytecode::Executable const&) const;
  779. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  780. void replace_references_impl(Register, Register) { }
  781. private:
  782. HashMap<u32, Variable> m_variables;
  783. };
  784. class GetIterator final : public Instruction {
  785. public:
  786. GetIterator()
  787. : Instruction(Type::GetIterator)
  788. {
  789. }
  790. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  791. String to_string_impl(Bytecode::Executable const&) const;
  792. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  793. void replace_references_impl(Register, Register) { }
  794. };
  795. class GetObjectPropertyIterator final : public Instruction {
  796. public:
  797. GetObjectPropertyIterator()
  798. : Instruction(Type::GetObjectPropertyIterator)
  799. {
  800. }
  801. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  802. String to_string_impl(Bytecode::Executable const&) const;
  803. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  804. void replace_references_impl(Register, Register) { }
  805. };
  806. class IteratorNext final : public Instruction {
  807. public:
  808. IteratorNext()
  809. : Instruction(Type::IteratorNext)
  810. {
  811. }
  812. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  813. String to_string_impl(Bytecode::Executable const&) const;
  814. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  815. void replace_references_impl(Register, Register) { }
  816. };
  817. class IteratorResultDone final : public Instruction {
  818. public:
  819. IteratorResultDone()
  820. : Instruction(Type::IteratorResultDone)
  821. {
  822. }
  823. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  824. String to_string_impl(Bytecode::Executable const&) const;
  825. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  826. void replace_references_impl(Register, Register) { }
  827. };
  828. class IteratorResultValue final : public Instruction {
  829. public:
  830. IteratorResultValue()
  831. : Instruction(Type::IteratorResultValue)
  832. {
  833. }
  834. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  835. String to_string_impl(Bytecode::Executable const&) const;
  836. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  837. void replace_references_impl(Register, Register) { }
  838. };
  839. class ResolveThisBinding final : public Instruction {
  840. public:
  841. explicit ResolveThisBinding()
  842. : Instruction(Type::ResolveThisBinding)
  843. {
  844. }
  845. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  846. String to_string_impl(Bytecode::Executable const&) const;
  847. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  848. void replace_references_impl(Register, Register) { }
  849. };
  850. class GetNewTarget final : public Instruction {
  851. public:
  852. explicit GetNewTarget()
  853. : Instruction(Type::GetNewTarget)
  854. {
  855. }
  856. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  857. String to_string_impl(Bytecode::Executable const&) const;
  858. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  859. void replace_references_impl(Register, Register) { }
  860. };
  861. class TypeofVariable final : public Instruction {
  862. public:
  863. explicit TypeofVariable(IdentifierTableIndex identifier)
  864. : Instruction(Type::TypeofVariable)
  865. , m_identifier(identifier)
  866. {
  867. }
  868. ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
  869. String to_string_impl(Bytecode::Executable const&) const;
  870. void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
  871. void replace_references_impl(Register, Register) { }
  872. private:
  873. IdentifierTableIndex m_identifier;
  874. };
  875. }
  876. namespace JS::Bytecode {
  877. ALWAYS_INLINE ThrowCompletionOr<void> Instruction::execute(Bytecode::Interpreter& interpreter) const
  878. {
  879. #define __BYTECODE_OP(op) \
  880. case Instruction::Type::op: \
  881. return static_cast<Bytecode::Op::op const&>(*this).execute_impl(interpreter);
  882. switch (type()) {
  883. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  884. default:
  885. VERIFY_NOT_REACHED();
  886. }
  887. #undef __BYTECODE_OP
  888. }
  889. ALWAYS_INLINE void Instruction::replace_references(BasicBlock const& from, BasicBlock const& to)
  890. {
  891. #define __BYTECODE_OP(op) \
  892. case Instruction::Type::op: \
  893. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  894. switch (type()) {
  895. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  896. default:
  897. VERIFY_NOT_REACHED();
  898. }
  899. #undef __BYTECODE_OP
  900. }
  901. ALWAYS_INLINE void Instruction::replace_references(Register from, Register to)
  902. {
  903. #define __BYTECODE_OP(op) \
  904. case Instruction::Type::op: \
  905. return static_cast<Bytecode::Op::op&>(*this).replace_references_impl(from, to);
  906. switch (type()) {
  907. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  908. default:
  909. VERIFY_NOT_REACHED();
  910. }
  911. #undef __BYTECODE_OP
  912. }
  913. ALWAYS_INLINE size_t Instruction::length() const
  914. {
  915. if (type() == Type::NewArray)
  916. return round_up_to_power_of_two(static_cast<Op::NewArray const&>(*this).length_impl(), alignof(void*));
  917. if (type() == Type::CopyObjectExcludingProperties)
  918. return round_up_to_power_of_two(static_cast<Op::CopyObjectExcludingProperties const&>(*this).length_impl(), alignof(void*));
  919. #define __BYTECODE_OP(op) \
  920. case Type::op: \
  921. return sizeof(Op::op);
  922. switch (type()) {
  923. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  924. default:
  925. VERIFY_NOT_REACHED();
  926. }
  927. #undef __BYTECODE_OP
  928. }
  929. ALWAYS_INLINE bool Instruction::is_terminator() const
  930. {
  931. #define __BYTECODE_OP(op) \
  932. case Type::op: \
  933. return Op::op::IsTerminator;
  934. switch (type()) {
  935. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  936. default:
  937. VERIFY_NOT_REACHED();
  938. }
  939. #undef __BYTECODE_OP
  940. }
  941. }