Op.h 50 KB

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