From aff51f7cfd7d9542a3fa140777349678fd90e359 Mon Sep 17 00:00:00 2001 From: davidot Date: Sun, 11 Sep 2022 10:48:00 +0200 Subject: [PATCH] test262-runner: Don't create a VM and Interpreter if just parsing If a test is supposed to fail during parse or early phase we can stop after parsing. Because phases in modules are not as clear we don't skip the other parts for modules. --- Tests/LibJS/test262-runner.cpp | 117 +++++++++++++++++---------------- 1 file changed, 60 insertions(+), 57 deletions(-) diff --git a/Tests/LibJS/test262-runner.cpp b/Tests/LibJS/test262-runner.cpp index a63763933d..c0cf102369 100644 --- a/Tests/LibJS/test262-runner.cpp +++ b/Tests/LibJS/test262-runner.cpp @@ -172,61 +172,6 @@ static Result, TestError> parse_harness_files(JS::R return program_or_error.release_value().get>(); } -static Result run_test(StringView source, StringView filepath, JS::Program::Type program_type, Vector const& harness_files) -{ - if (s_parse_only) { - // Creating the vm and interpreter is heavy so we just parse directly here. - auto parser = JS::Parser(JS::Lexer(source, filepath), program_type); - auto program_or_error = parser.parse_program(); - if (parser.has_errors()) { - return TestError { - NegativePhase::ParseOrEarly, - "SyntaxError", - parser.errors()[0].to_string(), - "" - }; - } - return {}; - } - - auto vm = JS::VM::create(); - vm->enable_default_host_import_module_dynamically_hook(); - auto ast_interpreter = JS::Interpreter::create(*vm); - auto& realm = ast_interpreter->realm(); - - auto program_or_error = parse_program(realm, source, filepath, program_type); - if (program_or_error.is_error()) - return program_or_error.release_error(); - - OwnPtr bytecode_interpreter = nullptr; - if (s_use_bytecode) - bytecode_interpreter = make(realm); - - auto run_with_interpreter = [&](ScriptOrModuleProgram& program) { - if (s_use_bytecode) - return run_program(*bytecode_interpreter, program); - return run_program(*ast_interpreter, program); - }; - - for (auto& harness_file : harness_files) { - auto harness_program_or_error = parse_harness_files(realm, harness_file); - if (harness_program_or_error.is_error()) - return harness_program_or_error.release_error(); - ScriptOrModuleProgram harness_program { harness_program_or_error.release_value() }; - auto result = run_with_interpreter(harness_program); - if (result.is_error()) { - return TestError { - NegativePhase::Harness, - result.error().type, - result.error().details, - harness_file - }; - } - } - - return run_with_interpreter(program_or_error.value()); -} - enum class StrictMode { Both, NoStrict, @@ -249,6 +194,64 @@ struct TestMetadata { StringView type; }; +static Result run_test(StringView source, StringView filepath, TestMetadata const& metadata) +{ + if (s_parse_only || (metadata.is_negative && metadata.phase == NegativePhase::ParseOrEarly && metadata.program_type != JS::Program::Type::Module)) { + // Creating the vm and interpreter is heavy so we just parse directly here. + // We can also skip if we know the test is supposed to fail during parse + // time. Unfortunately the phases of modules are not as clear and thus we + // only do this for scripts. See also the comment at the end of verify_test. + auto parser = JS::Parser(JS::Lexer(source, filepath), metadata.program_type); + auto program_or_error = parser.parse_program(); + if (parser.has_errors()) { + return TestError { + NegativePhase::ParseOrEarly, + "SyntaxError", + parser.errors()[0].to_string(), + "" + }; + } + return {}; + } + + auto vm = JS::VM::create(); + vm->enable_default_host_import_module_dynamically_hook(); + auto ast_interpreter = JS::Interpreter::create(*vm); + auto& realm = ast_interpreter->realm(); + + auto program_or_error = parse_program(realm, source, filepath, metadata.program_type); + if (program_or_error.is_error()) + return program_or_error.release_error(); + + OwnPtr bytecode_interpreter = nullptr; + if (s_use_bytecode) + bytecode_interpreter = make(realm); + + auto run_with_interpreter = [&](ScriptOrModuleProgram& program) { + if (s_use_bytecode) + return run_program(*bytecode_interpreter, program); + return run_program(*ast_interpreter, program); + }; + + for (auto& harness_file : metadata.harness_files) { + auto harness_program_or_error = parse_harness_files(realm, harness_file); + if (harness_program_or_error.is_error()) + return harness_program_or_error.release_error(); + ScriptOrModuleProgram harness_program { harness_program_or_error.release_value() }; + auto result = run_with_interpreter(harness_program); + if (result.is_error()) { + return TestError { + NegativePhase::Harness, + result.error().type, + result.error().details, + harness_file + }; + } + } + + return run_with_interpreter(program_or_error.value()); +} + static Result extract_metadata(StringView source) { auto lines = source.lines(); @@ -716,7 +719,7 @@ int main(int argc, char** argv) result_object.set("strict_mode", false); ARM_TIMER(); - auto result = run_test(original_contents, path, metadata.program_type, metadata.harness_files); + auto result = run_test(original_contents, path, metadata); DISARM_TIMER(); String first_output = collect_output(); @@ -739,7 +742,7 @@ int main(int argc, char** argv) result_object.set("strict_mode", true); ARM_TIMER(); - auto result = run_test(with_strict, path, metadata.program_type, metadata.harness_files); + auto result = run_test(with_strict, path, metadata); DISARM_TIMER(); String first_output = collect_output();