Op.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  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. #include <AK/HashTable.h>
  9. #include <LibJS/Bytecode/Interpreter.h>
  10. #include <LibJS/Bytecode/Op.h>
  11. #include <LibJS/Runtime/AbstractOperations.h>
  12. #include <LibJS/Runtime/Array.h>
  13. #include <LibJS/Runtime/BigInt.h>
  14. #include <LibJS/Runtime/DeclarativeEnvironment.h>
  15. #include <LibJS/Runtime/ECMAScriptFunctionObject.h>
  16. #include <LibJS/Runtime/Environment.h>
  17. #include <LibJS/Runtime/GlobalObject.h>
  18. #include <LibJS/Runtime/IteratorOperations.h>
  19. #include <LibJS/Runtime/RegExpObject.h>
  20. #include <LibJS/Runtime/Value.h>
  21. namespace JS::Bytecode {
  22. String Instruction::to_string(Bytecode::Executable const& executable) const
  23. {
  24. #define __BYTECODE_OP(op) \
  25. case Instruction::Type::op: \
  26. return static_cast<Bytecode::Op::op const&>(*this).to_string_impl(executable);
  27. switch (type()) {
  28. ENUMERATE_BYTECODE_OPS(__BYTECODE_OP)
  29. default:
  30. VERIFY_NOT_REACHED();
  31. }
  32. #undef __BYTECODE_OP
  33. }
  34. }
  35. namespace JS::Bytecode::Op {
  36. void Load::execute_impl(Bytecode::Interpreter& interpreter) const
  37. {
  38. interpreter.accumulator() = interpreter.reg(m_src);
  39. }
  40. void LoadImmediate::execute_impl(Bytecode::Interpreter& interpreter) const
  41. {
  42. interpreter.accumulator() = m_value;
  43. }
  44. void Store::execute_impl(Bytecode::Interpreter& interpreter) const
  45. {
  46. interpreter.reg(m_dst) = interpreter.accumulator();
  47. }
  48. static ThrowCompletionOr<Value> abstract_inequals(GlobalObject& global_object, Value src1, Value src2)
  49. {
  50. return Value(!TRY(is_loosely_equal(global_object, src1, src2)));
  51. }
  52. static ThrowCompletionOr<Value> abstract_equals(GlobalObject& global_object, Value src1, Value src2)
  53. {
  54. return Value(TRY(is_loosely_equal(global_object, src1, src2)));
  55. }
  56. static ThrowCompletionOr<Value> typed_inequals(GlobalObject&, Value src1, Value src2)
  57. {
  58. return Value(!is_strictly_equal(src1, src2));
  59. }
  60. static ThrowCompletionOr<Value> typed_equals(GlobalObject&, Value src1, Value src2)
  61. {
  62. return Value(is_strictly_equal(src1, src2));
  63. }
  64. #define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \
  65. void OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \
  66. { \
  67. auto lhs = interpreter.reg(m_lhs_reg); \
  68. auto rhs = interpreter.accumulator(); \
  69. auto result_or_error = op_snake_case(interpreter.global_object(), lhs, rhs); \
  70. if (result_or_error.is_error()) \
  71. return; \
  72. interpreter.accumulator() = result_or_error.release_value(); \
  73. } \
  74. String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \
  75. { \
  76. return String::formatted(#OpTitleCase " {}", m_lhs_reg); \
  77. }
  78. JS_ENUMERATE_COMMON_BINARY_OPS(JS_DEFINE_COMMON_BINARY_OP)
  79. static ThrowCompletionOr<Value> not_(GlobalObject&, Value value)
  80. {
  81. return Value(!value.to_boolean());
  82. }
  83. static ThrowCompletionOr<Value> typeof_(GlobalObject& global_object, Value value)
  84. {
  85. return Value(js_string(global_object.vm(), value.typeof()));
  86. }
  87. #define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \
  88. void OpTitleCase::execute_impl(Bytecode::Interpreter& interpreter) const \
  89. { \
  90. auto result_or_error = op_snake_case(interpreter.global_object(), interpreter.accumulator()); \
  91. if (result_or_error.is_error()) \
  92. return; \
  93. interpreter.accumulator() = result_or_error.release_value(); \
  94. } \
  95. String OpTitleCase::to_string_impl(Bytecode::Executable const&) const \
  96. { \
  97. return #OpTitleCase; \
  98. }
  99. JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP)
  100. void NewBigInt::execute_impl(Bytecode::Interpreter& interpreter) const
  101. {
  102. interpreter.accumulator() = js_bigint(interpreter.vm().heap(), m_bigint);
  103. }
  104. void NewArray::execute_impl(Bytecode::Interpreter& interpreter) const
  105. {
  106. Vector<Value> elements;
  107. elements.ensure_capacity(m_element_count);
  108. for (size_t i = 0; i < m_element_count; i++)
  109. elements.append(interpreter.reg(m_elements[i]));
  110. interpreter.accumulator() = Array::create_from(interpreter.global_object(), elements);
  111. }
  112. void IteratorToArray::execute_impl(Bytecode::Interpreter& interpreter) const
  113. {
  114. auto& global_object = interpreter.global_object();
  115. auto iterator_or_error = interpreter.accumulator().to_object(global_object);
  116. if (iterator_or_error.is_error())
  117. return;
  118. auto* iterator = iterator_or_error.release_value();
  119. auto* array = MUST(Array::create(global_object, 0));
  120. size_t index = 0;
  121. while (true) {
  122. auto iterator_result_or_error = iterator_next(*iterator);
  123. if (iterator_result_or_error.is_error())
  124. return;
  125. auto* iterator_result = iterator_result_or_error.release_value();
  126. auto complete_or_error = iterator_complete(global_object, *iterator_result);
  127. if (complete_or_error.is_error())
  128. return;
  129. auto complete = complete_or_error.release_value();
  130. if (complete) {
  131. interpreter.accumulator() = array;
  132. return;
  133. }
  134. auto value_or_error = iterator_value(global_object, *iterator_result);
  135. if (value_or_error.is_error())
  136. return;
  137. auto value = value_or_error.release_value();
  138. MUST(array->create_data_property_or_throw(index, value));
  139. index++;
  140. }
  141. }
  142. void NewString::execute_impl(Bytecode::Interpreter& interpreter) const
  143. {
  144. interpreter.accumulator() = js_string(interpreter.vm(), interpreter.current_executable().get_string(m_string));
  145. }
  146. void NewObject::execute_impl(Bytecode::Interpreter& interpreter) const
  147. {
  148. interpreter.accumulator() = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
  149. }
  150. void NewRegExp::execute_impl(Bytecode::Interpreter& interpreter) const
  151. {
  152. auto source = interpreter.current_executable().get_string(m_source_index);
  153. auto flags = interpreter.current_executable().get_string(m_flags_index);
  154. interpreter.accumulator() = regexp_create(interpreter.global_object(), js_string(interpreter.vm(), source), js_string(interpreter.vm(), flags));
  155. }
  156. void CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpreter) const
  157. {
  158. auto from_object_or_error = interpreter.reg(m_from_object).to_object(interpreter.global_object());
  159. if (from_object_or_error.is_error())
  160. return;
  161. auto* from_object = from_object_or_error.release_value();
  162. auto* to_object = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
  163. HashTable<Value, ValueTraits> excluded_names;
  164. for (size_t i = 0; i < m_excluded_names_count; ++i) {
  165. excluded_names.set(interpreter.reg(m_excluded_names[i]));
  166. if (interpreter.vm().exception())
  167. return;
  168. }
  169. auto own_keys_or_error = from_object->internal_own_property_keys();
  170. if (own_keys_or_error.is_error())
  171. return;
  172. auto own_keys = own_keys_or_error.release_value();
  173. for (auto& key : own_keys) {
  174. if (!excluded_names.contains(key)) {
  175. auto property_name_or_error = key.to_property_key(interpreter.global_object());
  176. if (property_name_or_error.is_error())
  177. return;
  178. PropertyName property_name = property_name_or_error.release_value();
  179. auto property_value_or_error = from_object->get(property_name);
  180. if (property_value_or_error.is_error())
  181. return;
  182. auto property_value = property_value_or_error.release_value();
  183. to_object->define_direct_property(property_name, property_value, JS::default_attributes);
  184. }
  185. }
  186. interpreter.accumulator() = to_object;
  187. }
  188. void ConcatString::execute_impl(Bytecode::Interpreter& interpreter) const
  189. {
  190. auto result_or_error = add(interpreter.global_object(), interpreter.reg(m_lhs), interpreter.accumulator());
  191. if (result_or_error.is_error())
  192. return;
  193. interpreter.reg(m_lhs) = result_or_error.release_value();
  194. }
  195. void GetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
  196. {
  197. auto& vm = interpreter.vm();
  198. auto reference = vm.resolve_binding(interpreter.current_executable().get_string(m_identifier));
  199. if (vm.exception())
  200. return;
  201. interpreter.accumulator() = reference.get_value(interpreter.global_object());
  202. }
  203. void SetVariable::execute_impl(Bytecode::Interpreter& interpreter) const
  204. {
  205. auto& vm = interpreter.vm();
  206. auto reference = vm.resolve_binding(interpreter.current_executable().get_string(m_identifier));
  207. if (vm.exception())
  208. return;
  209. reference.put_value(interpreter.global_object(), interpreter.accumulator());
  210. }
  211. void GetById::execute_impl(Bytecode::Interpreter& interpreter) const
  212. {
  213. auto object_or_error = interpreter.accumulator().to_object(interpreter.global_object());
  214. if (object_or_error.is_error())
  215. return;
  216. auto* object = object_or_error.release_value();
  217. auto value_or_error = object->get(interpreter.current_executable().get_string(m_property));
  218. if (value_or_error.is_error())
  219. return;
  220. interpreter.accumulator() = value_or_error.release_value();
  221. }
  222. void PutById::execute_impl(Bytecode::Interpreter& interpreter) const
  223. {
  224. auto object_or_error = interpreter.reg(m_base).to_object(interpreter.global_object());
  225. if (object_or_error.is_error())
  226. return;
  227. auto* object = object_or_error.release_value();
  228. MUST(object->set(interpreter.current_executable().get_string(m_property), interpreter.accumulator(), Object::ShouldThrowExceptions::Yes));
  229. }
  230. void Jump::execute_impl(Bytecode::Interpreter& interpreter) const
  231. {
  232. interpreter.jump(*m_true_target);
  233. }
  234. void Jump::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  235. {
  236. if (m_true_target.has_value() && &m_true_target->block() == &from)
  237. m_true_target = Label { to };
  238. if (m_false_target.has_value() && &m_false_target->block() == &from)
  239. m_false_target = Label { to };
  240. }
  241. void JumpConditional::execute_impl(Bytecode::Interpreter& interpreter) const
  242. {
  243. VERIFY(m_true_target.has_value());
  244. VERIFY(m_false_target.has_value());
  245. auto result = interpreter.accumulator();
  246. if (result.to_boolean())
  247. interpreter.jump(m_true_target.value());
  248. else
  249. interpreter.jump(m_false_target.value());
  250. }
  251. void JumpNullish::execute_impl(Bytecode::Interpreter& interpreter) const
  252. {
  253. VERIFY(m_true_target.has_value());
  254. VERIFY(m_false_target.has_value());
  255. auto result = interpreter.accumulator();
  256. if (result.is_nullish())
  257. interpreter.jump(m_true_target.value());
  258. else
  259. interpreter.jump(m_false_target.value());
  260. }
  261. void JumpUndefined::execute_impl(Bytecode::Interpreter& interpreter) const
  262. {
  263. VERIFY(m_true_target.has_value());
  264. VERIFY(m_false_target.has_value());
  265. auto result = interpreter.accumulator();
  266. if (result.is_undefined())
  267. interpreter.jump(m_true_target.value());
  268. else
  269. interpreter.jump(m_false_target.value());
  270. }
  271. void Call::execute_impl(Bytecode::Interpreter& interpreter) const
  272. {
  273. auto callee = interpreter.reg(m_callee);
  274. if (!callee.is_function()) {
  275. TODO();
  276. }
  277. auto& function = callee.as_function();
  278. auto this_value = interpreter.reg(m_this_value);
  279. Value return_value;
  280. if (m_argument_count == 0 && m_type == CallType::Call) {
  281. auto return_value_or_error = interpreter.vm().call(function, this_value);
  282. if (!return_value_or_error.is_error())
  283. return_value = return_value_or_error.release_value();
  284. } else {
  285. MarkedValueList argument_values { interpreter.vm().heap() };
  286. for (size_t i = 0; i < m_argument_count; ++i) {
  287. argument_values.append(interpreter.reg(m_arguments[i]));
  288. }
  289. if (m_type == CallType::Call) {
  290. auto return_value_or_error = interpreter.vm().call(function, this_value, move(argument_values));
  291. if (return_value_or_error.is_error())
  292. return;
  293. return_value = return_value_or_error.release_value();
  294. } else {
  295. auto return_value_or_error = construct(interpreter.global_object(), function, move(argument_values));
  296. if (return_value_or_error.is_error())
  297. return;
  298. return_value = return_value_or_error.release_value();
  299. }
  300. }
  301. interpreter.accumulator() = return_value;
  302. }
  303. void NewFunction::execute_impl(Bytecode::Interpreter& interpreter) const
  304. {
  305. auto& vm = interpreter.vm();
  306. interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.global_object(), m_function_node.name(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), vm.running_execution_context().private_environment, m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.might_need_arguments_object(), m_function_node.is_arrow_function());
  307. }
  308. void Return::execute_impl(Bytecode::Interpreter& interpreter) const
  309. {
  310. interpreter.do_return(interpreter.accumulator().value_or(js_undefined()));
  311. }
  312. void Increment::execute_impl(Bytecode::Interpreter& interpreter) const
  313. {
  314. auto old_value_or_error = interpreter.accumulator().to_numeric(interpreter.global_object());
  315. if (old_value_or_error.is_error())
  316. return;
  317. auto old_value = old_value_or_error.release_value();
  318. if (old_value.is_number())
  319. interpreter.accumulator() = Value(old_value.as_double() + 1);
  320. else
  321. interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().plus(Crypto::SignedBigInteger { 1 }));
  322. }
  323. void Decrement::execute_impl(Bytecode::Interpreter& interpreter) const
  324. {
  325. auto old_value_or_error = interpreter.accumulator().to_numeric(interpreter.global_object());
  326. if (old_value_or_error.is_error())
  327. return;
  328. auto old_value = old_value_or_error.release_value();
  329. if (old_value.is_number())
  330. interpreter.accumulator() = Value(old_value.as_double() - 1);
  331. else
  332. interpreter.accumulator() = js_bigint(interpreter.vm().heap(), old_value.as_bigint().big_integer().minus(Crypto::SignedBigInteger { 1 }));
  333. }
  334. void Throw::execute_impl(Bytecode::Interpreter& interpreter) const
  335. {
  336. interpreter.vm().throw_exception(interpreter.global_object(), interpreter.accumulator());
  337. }
  338. void EnterUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const
  339. {
  340. interpreter.enter_unwind_context(m_handler_target, m_finalizer_target);
  341. interpreter.jump(m_entry_point);
  342. }
  343. void EnterUnwindContext::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  344. {
  345. if (&m_entry_point.block() == &from)
  346. m_entry_point = Label { to };
  347. if (m_handler_target.has_value() && &m_handler_target->block() == &from)
  348. m_handler_target = Label { to };
  349. if (m_finalizer_target.has_value() && &m_finalizer_target->block() == &from)
  350. m_finalizer_target = Label { to };
  351. }
  352. void LeaveUnwindContext::execute_impl(Bytecode::Interpreter& interpreter) const
  353. {
  354. interpreter.leave_unwind_context();
  355. }
  356. void ContinuePendingUnwind::execute_impl(Bytecode::Interpreter& interpreter) const
  357. {
  358. interpreter.continue_pending_unwind(m_resume_target);
  359. }
  360. void ContinuePendingUnwind::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  361. {
  362. if (&m_resume_target.block() == &from)
  363. m_resume_target = Label { to };
  364. }
  365. void PushDeclarativeEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
  366. {
  367. auto* environment = interpreter.vm().heap().allocate<DeclarativeEnvironment>(interpreter.global_object(), interpreter.vm().lexical_environment());
  368. interpreter.vm().running_execution_context().lexical_environment = environment;
  369. interpreter.vm().running_execution_context().variable_environment = environment;
  370. }
  371. void Yield::execute_impl(Bytecode::Interpreter& interpreter) const
  372. {
  373. auto yielded_value = interpreter.accumulator().value_or(js_undefined());
  374. auto object = JS::Object::create(interpreter.global_object(), nullptr);
  375. object->define_direct_property("result", yielded_value, JS::default_attributes);
  376. if (m_continuation_label.has_value())
  377. object->define_direct_property("continuation", Value(static_cast<double>(reinterpret_cast<u64>(&m_continuation_label->block()))), JS::default_attributes);
  378. else
  379. object->define_direct_property("continuation", Value(0), JS::default_attributes);
  380. interpreter.do_return(object);
  381. }
  382. void Yield::replace_references_impl(BasicBlock const& from, BasicBlock const& to)
  383. {
  384. if (m_continuation_label.has_value() && &m_continuation_label->block() == &from)
  385. m_continuation_label = Label { to };
  386. }
  387. void GetByValue::execute_impl(Bytecode::Interpreter& interpreter) const
  388. {
  389. auto object_or_error = interpreter.reg(m_base).to_object(interpreter.global_object());
  390. if (object_or_error.is_error())
  391. return;
  392. auto* object = object_or_error.release_value();
  393. auto property_key_or_error = interpreter.accumulator().to_property_key(interpreter.global_object());
  394. if (property_key_or_error.is_error())
  395. return;
  396. auto value_or_error = object->get(property_key_or_error.release_value());
  397. if (value_or_error.is_error())
  398. return;
  399. interpreter.accumulator() = value_or_error.release_value();
  400. }
  401. void PutByValue::execute_impl(Bytecode::Interpreter& interpreter) const
  402. {
  403. auto object_or_error = interpreter.reg(m_base).to_object(interpreter.global_object());
  404. if (object_or_error.is_error())
  405. return;
  406. auto* object = object_or_error.release_value();
  407. auto property_key_or_error = interpreter.reg(m_property).to_property_key(interpreter.global_object());
  408. if (property_key_or_error.is_error())
  409. return;
  410. MUST(object->set(property_key_or_error.release_value(), interpreter.accumulator(), Object::ShouldThrowExceptions::Yes));
  411. }
  412. void GetIterator::execute_impl(Bytecode::Interpreter& interpreter) const
  413. {
  414. auto iterator_or_error = get_iterator(interpreter.global_object(), interpreter.accumulator());
  415. if (iterator_or_error.is_error())
  416. return;
  417. interpreter.accumulator() = iterator_or_error.release_value();
  418. }
  419. void IteratorNext::execute_impl(Bytecode::Interpreter& interpreter) const
  420. {
  421. auto object_or_error = interpreter.accumulator().to_object(interpreter.global_object());
  422. if (object_or_error.is_error())
  423. return;
  424. auto* object = object_or_error.release_value();
  425. auto iterator_result_or_error = iterator_next(*object);
  426. if (iterator_result_or_error.is_error())
  427. return;
  428. auto* iterator_result = iterator_result_or_error.release_value();
  429. interpreter.accumulator() = iterator_result;
  430. }
  431. void IteratorResultDone::execute_impl(Bytecode::Interpreter& interpreter) const
  432. {
  433. auto iterator_result_or_error = interpreter.accumulator().to_object(interpreter.global_object());
  434. if (iterator_result_or_error.is_error())
  435. return;
  436. auto* iterator_result = iterator_result_or_error.release_value();
  437. auto complete_or_error = iterator_complete(interpreter.global_object(), *iterator_result);
  438. if (complete_or_error.is_error())
  439. return;
  440. auto complete = complete_or_error.release_value();
  441. interpreter.accumulator() = Value(complete);
  442. }
  443. void IteratorResultValue::execute_impl(Bytecode::Interpreter& interpreter) const
  444. {
  445. auto iterator_result_or_error = interpreter.accumulator().to_object(interpreter.global_object());
  446. if (iterator_result_or_error.is_error())
  447. return;
  448. auto* iterator_result = iterator_result_or_error.release_value();
  449. auto value_or_error = iterator_value(interpreter.global_object(), *iterator_result);
  450. if (value_or_error.is_error())
  451. return;
  452. auto value = value_or_error.release_value();
  453. interpreter.accumulator() = value;
  454. }
  455. void NewClass::execute_impl(Bytecode::Interpreter&) const
  456. {
  457. (void)m_class_expression;
  458. TODO();
  459. }
  460. String Load::to_string_impl(Bytecode::Executable const&) const
  461. {
  462. return String::formatted("Load {}", m_src);
  463. }
  464. String LoadImmediate::to_string_impl(Bytecode::Executable const&) const
  465. {
  466. return String::formatted("LoadImmediate {}", m_value);
  467. }
  468. String Store::to_string_impl(Bytecode::Executable const&) const
  469. {
  470. return String::formatted("Store {}", m_dst);
  471. }
  472. String NewBigInt::to_string_impl(Bytecode::Executable const&) const
  473. {
  474. return String::formatted("NewBigInt \"{}\"", m_bigint.to_base(10));
  475. }
  476. String NewArray::to_string_impl(Bytecode::Executable const&) const
  477. {
  478. StringBuilder builder;
  479. builder.append("NewArray");
  480. if (m_element_count != 0) {
  481. builder.append(" [");
  482. for (size_t i = 0; i < m_element_count; ++i) {
  483. builder.appendff("{}", m_elements[i]);
  484. if (i != m_element_count - 1)
  485. builder.append(',');
  486. }
  487. builder.append(']');
  488. }
  489. return builder.to_string();
  490. }
  491. String IteratorToArray::to_string_impl(const Bytecode::Executable&) const
  492. {
  493. return "IteratorToArray";
  494. }
  495. String NewString::to_string_impl(Bytecode::Executable const& executable) const
  496. {
  497. return String::formatted("NewString {} (\"{}\")", m_string, executable.string_table->get(m_string));
  498. }
  499. String NewObject::to_string_impl(Bytecode::Executable const&) const
  500. {
  501. return "NewObject";
  502. }
  503. String NewRegExp::to_string_impl(Bytecode::Executable const& executable) const
  504. {
  505. return String::formatted("NewRegExp source:{} (\"{}\") flags:{} (\"{}\")", m_source_index, executable.get_string(m_source_index), m_flags_index, executable.get_string(m_flags_index));
  506. }
  507. String CopyObjectExcludingProperties::to_string_impl(const Bytecode::Executable&) const
  508. {
  509. StringBuilder builder;
  510. builder.appendff("CopyObjectExcludingProperties from:{}", m_from_object);
  511. if (m_excluded_names_count != 0) {
  512. builder.append(" excluding:[");
  513. for (size_t i = 0; i < m_excluded_names_count; ++i) {
  514. builder.appendff("{}", m_excluded_names[i]);
  515. if (i != m_excluded_names_count - 1)
  516. builder.append(',');
  517. }
  518. builder.append(']');
  519. }
  520. return builder.to_string();
  521. }
  522. String ConcatString::to_string_impl(Bytecode::Executable const&) const
  523. {
  524. return String::formatted("ConcatString {}", m_lhs);
  525. }
  526. String GetVariable::to_string_impl(Bytecode::Executable const& executable) const
  527. {
  528. return String::formatted("GetVariable {} ({})", m_identifier, executable.string_table->get(m_identifier));
  529. }
  530. String SetVariable::to_string_impl(Bytecode::Executable const& executable) const
  531. {
  532. return String::formatted("SetVariable {} ({})", m_identifier, executable.string_table->get(m_identifier));
  533. }
  534. String PutById::to_string_impl(Bytecode::Executable const& executable) const
  535. {
  536. return String::formatted("PutById base:{}, property:{} ({})", m_base, m_property, executable.string_table->get(m_property));
  537. }
  538. String GetById::to_string_impl(Bytecode::Executable const& executable) const
  539. {
  540. return String::formatted("GetById {} ({})", m_property, executable.string_table->get(m_property));
  541. }
  542. String Jump::to_string_impl(Bytecode::Executable const&) const
  543. {
  544. if (m_true_target.has_value())
  545. return String::formatted("Jump {}", *m_true_target);
  546. return String::formatted("Jump <empty>");
  547. }
  548. String JumpConditional::to_string_impl(Bytecode::Executable const&) const
  549. {
  550. auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>";
  551. auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>";
  552. return String::formatted("JumpConditional true:{} false:{}", true_string, false_string);
  553. }
  554. String JumpNullish::to_string_impl(Bytecode::Executable const&) const
  555. {
  556. auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>";
  557. auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>";
  558. return String::formatted("JumpNullish null:{} nonnull:{}", true_string, false_string);
  559. }
  560. String JumpUndefined::to_string_impl(Bytecode::Executable const&) const
  561. {
  562. auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>";
  563. auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>";
  564. return String::formatted("JumpUndefined undefined:{} not undefined:{}", true_string, false_string);
  565. }
  566. String Call::to_string_impl(Bytecode::Executable const&) const
  567. {
  568. StringBuilder builder;
  569. builder.appendff("Call callee:{}, this:{}", m_callee, m_this_value);
  570. if (m_argument_count != 0) {
  571. builder.append(", arguments:[");
  572. for (size_t i = 0; i < m_argument_count; ++i) {
  573. builder.appendff("{}", m_arguments[i]);
  574. if (i != m_argument_count - 1)
  575. builder.append(',');
  576. }
  577. builder.append(']');
  578. }
  579. return builder.to_string();
  580. }
  581. String NewFunction::to_string_impl(Bytecode::Executable const&) const
  582. {
  583. return "NewFunction";
  584. }
  585. String NewClass::to_string_impl(Bytecode::Executable const&) const
  586. {
  587. return "NewClass";
  588. }
  589. String Return::to_string_impl(Bytecode::Executable const&) const
  590. {
  591. return "Return";
  592. }
  593. String Increment::to_string_impl(Bytecode::Executable const&) const
  594. {
  595. return "Increment";
  596. }
  597. String Decrement::to_string_impl(Bytecode::Executable const&) const
  598. {
  599. return "Decrement";
  600. }
  601. String Throw::to_string_impl(Bytecode::Executable const&) const
  602. {
  603. return "Throw";
  604. }
  605. String EnterUnwindContext::to_string_impl(Bytecode::Executable const&) const
  606. {
  607. auto handler_string = m_handler_target.has_value() ? String::formatted("{}", *m_handler_target) : "<empty>";
  608. auto finalizer_string = m_finalizer_target.has_value() ? String::formatted("{}", *m_finalizer_target) : "<empty>";
  609. return String::formatted("EnterUnwindContext handler:{} finalizer:{} entry:{}", handler_string, finalizer_string, m_entry_point);
  610. }
  611. String LeaveUnwindContext::to_string_impl(Bytecode::Executable const&) const
  612. {
  613. return "LeaveUnwindContext";
  614. }
  615. String ContinuePendingUnwind::to_string_impl(Bytecode::Executable const&) const
  616. {
  617. return String::formatted("ContinuePendingUnwind resume:{}", m_resume_target);
  618. }
  619. String PushDeclarativeEnvironment::to_string_impl(const Bytecode::Executable& executable) const
  620. {
  621. StringBuilder builder;
  622. builder.append("PushDeclarativeEnvironment");
  623. if (!m_variables.is_empty()) {
  624. builder.append(" {");
  625. Vector<String> names;
  626. for (auto& it : m_variables)
  627. names.append(executable.get_string(it.key));
  628. builder.join(", ", names);
  629. builder.append("}");
  630. }
  631. return builder.to_string();
  632. }
  633. String Yield::to_string_impl(Bytecode::Executable const&) const
  634. {
  635. if (m_continuation_label.has_value())
  636. return String::formatted("Yield continuation:@{}", m_continuation_label->block().name());
  637. return String::formatted("Yield return");
  638. }
  639. String GetByValue::to_string_impl(const Bytecode::Executable&) const
  640. {
  641. return String::formatted("GetByValue base:{}", m_base);
  642. }
  643. String PutByValue::to_string_impl(const Bytecode::Executable&) const
  644. {
  645. return String::formatted("PutByValue base:{}, property:{}", m_base, m_property);
  646. }
  647. String GetIterator::to_string_impl(Executable const&) const
  648. {
  649. return "GetIterator";
  650. }
  651. String IteratorNext::to_string_impl(Executable const&) const
  652. {
  653. return "IteratorNext";
  654. }
  655. String IteratorResultDone::to_string_impl(Executable const&) const
  656. {
  657. return "IteratorResultDone";
  658. }
  659. String IteratorResultValue::to_string_impl(Executable const&) const
  660. {
  661. return "IteratorResultValue";
  662. }
  663. }