diff --git a/Userland/Libraries/LibTest/JavaScriptTestRunner.h b/Userland/Libraries/LibTest/JavaScriptTestRunner.h index e85d7edfe2..57ce930e3b 100644 --- a/Userland/Libraries/LibTest/JavaScriptTestRunner.h +++ b/Userland/Libraries/LibTest/JavaScriptTestRunner.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -104,6 +105,8 @@ static consteval size_t __testjs_last() { return (AK::Detail::IntegralConstant g_vm; extern bool g_collect_on_every_allocation; +extern bool g_run_bytecode; +extern bool g_dump_bytecode; extern String g_currently_running_test; extern String g_test_glob; struct FunctionWithLength { @@ -385,12 +388,44 @@ inline JSFileResult TestRunner::run_file_test(const String& test_path) m_test_program = result.value(); } - interpreter->run(interpreter->global_object(), *m_test_program); + if (g_run_bytecode) { + auto unit = JS::Bytecode::Generator::generate(*m_test_program); + if (g_dump_bytecode) { + for (auto& block : unit.basic_blocks) + block.dump(unit); + if (!unit.string_table->is_empty()) { + outln(); + unit.string_table->dump(); + } + } + + JS::Bytecode::Interpreter bytecode_interpreter(interpreter->global_object()); + bytecode_interpreter.run(unit); + } else { + interpreter->run(interpreter->global_object(), *m_test_program); + } + + VERIFY(!g_vm->exception()); auto file_program = parse_file(test_path); if (file_program.is_error()) return { test_path, file_program.error() }; - interpreter->run(interpreter->global_object(), *file_program.value()); + if (g_run_bytecode) { + auto unit = JS::Bytecode::Generator::generate(*file_program.value()); + if (g_dump_bytecode) { + for (auto& block : unit.basic_blocks) + block.dump(unit); + if (!unit.string_table->is_empty()) { + outln(); + unit.string_table->dump(); + } + } + + JS::Bytecode::Interpreter bytecode_interpreter(interpreter->global_object()); + bytecode_interpreter.run(unit); + } else { + interpreter->run(interpreter->global_object(), *file_program.value()); + } if (g_vm->exception()) g_vm->clear_exception(); diff --git a/Userland/Libraries/LibTest/JavaScriptTestRunnerMain.cpp b/Userland/Libraries/LibTest/JavaScriptTestRunnerMain.cpp index 0d4da62907..215bdde576 100644 --- a/Userland/Libraries/LibTest/JavaScriptTestRunnerMain.cpp +++ b/Userland/Libraries/LibTest/JavaScriptTestRunnerMain.cpp @@ -14,6 +14,8 @@ namespace Test::JS { RefPtr<::JS::VM> g_vm; bool g_collect_on_every_allocation = false; +bool g_run_bytecode = false; +bool g_dump_bytecode = false; String g_currently_running_test; String g_test_glob; HashMap s_exposed_global_functions; @@ -103,6 +105,8 @@ int main(int argc, char** argv) }); args_parser.add_option(print_json, "Show results as JSON", "json", 'j'); args_parser.add_option(g_collect_on_every_allocation, "Collect garbage after every allocation", "collect-often", 'g'); + args_parser.add_option(g_run_bytecode, "Use the bytecode interpreter", "run-bytecode", 'b'); + args_parser.add_option(g_dump_bytecode, "Dump the bytecode", "dump-bytecode", 'd'); args_parser.add_option(g_test_glob, "Only run tests matching the given glob", "filter", 'f', "glob"); for (auto& entry : g_extra_args) args_parser.add_option(*entry.key, entry.value.get<0>().characters(), entry.value.get<1>().characters(), entry.value.get<2>()); @@ -116,6 +120,11 @@ int main(int argc, char** argv) AK::set_debug_enabled(false); } + if (g_dump_bytecode && !g_run_bytecode) { + warnln("--dump-bytecode can only be used when --run-bytecode is specified."); + return 1; + } + String test_root; if (specified_test_root) {