Interpreter.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Bytecode/Block.h>
  7. #include <LibJS/Bytecode/Instruction.h>
  8. #include <LibJS/Bytecode/Interpreter.h>
  9. #include <LibJS/Runtime/GlobalObject.h>
  10. namespace JS::Bytecode {
  11. static Interpreter* s_current;
  12. Interpreter* Interpreter::current()
  13. {
  14. return s_current;
  15. }
  16. Interpreter::Interpreter(GlobalObject& global_object)
  17. : m_vm(global_object.vm())
  18. , m_global_object(global_object)
  19. {
  20. VERIFY(!s_current);
  21. s_current = this;
  22. }
  23. Interpreter::~Interpreter()
  24. {
  25. VERIFY(s_current == this);
  26. s_current = nullptr;
  27. }
  28. Value Interpreter::run(Bytecode::Block const& block)
  29. {
  30. dbgln("Bytecode::Interpreter will run block {:p}", &block);
  31. if (vm().call_stack().is_empty()) {
  32. CallFrame global_call_frame;
  33. global_call_frame.this_value = &global_object();
  34. static FlyString global_execution_context_name = "(*BC* global execution context)";
  35. global_call_frame.function_name = global_execution_context_name;
  36. global_call_frame.scope = &global_object();
  37. VERIFY(!vm().exception());
  38. // FIXME: How do we know if we're in strict mode? Maybe the Bytecode::Block should know this?
  39. // global_call_frame.is_strict_mode = ???;
  40. vm().push_call_frame(global_call_frame, global_object());
  41. VERIFY(!vm().exception());
  42. }
  43. m_register_windows.append(make<RegisterWindow>());
  44. registers().resize(block.register_count());
  45. size_t pc = 0;
  46. while (pc < block.instructions().size()) {
  47. auto& instruction = block.instructions()[pc];
  48. instruction.execute(*this);
  49. if (m_pending_jump.has_value()) {
  50. pc = m_pending_jump.release_value();
  51. continue;
  52. }
  53. if (!m_return_value.is_empty())
  54. break;
  55. ++pc;
  56. }
  57. dbgln("Bytecode::Interpreter did run block {:p}", &block);
  58. for (size_t i = 0; i < registers().size(); ++i) {
  59. String value_string;
  60. if (registers()[i].is_empty())
  61. value_string = "(empty)";
  62. else
  63. value_string = registers()[i].to_string_without_side_effects();
  64. dbgln("[{:3}] {}", i, value_string);
  65. }
  66. m_register_windows.take_last();
  67. m_return_value = m_return_value.value_or(js_undefined());
  68. // NOTE: The return value from a called function is put into $0 in the caller context.
  69. if (!m_register_windows.is_empty())
  70. m_register_windows.last()[0] = m_return_value;
  71. if (vm().call_stack().size() == 1)
  72. vm().pop_call_frame();
  73. return m_return_value;
  74. }
  75. }