From 3abb8c53bb9ebcc55a7516a6dafbfddbc519648f Mon Sep 17 00:00:00 2001 From: Viktoria Shirunova Date: Thu, 27 Oct 2022 21:05:18 +0300 Subject: [PATCH] Universal runner: prepare test js files for running in JIT configuration: wrap the code with function and call it in a loop --jit-preheat-repeats times. This touches only Hermes and Test262 test suites. Signed-off-by: Viktoria Shirunova --- .../js/test-export-named-decl-expected.txt | 1 - .../runner/plugins/hermes/runner_js_hermes.py | 12 ++++-- test/runner/plugins/hermes/util_hermes.py | 40 +++++++++++++++++-- .../plugins/parser/parser-js-ignored.txt | 1 + .../plugins/test262/runner_js_test262.py | 14 +++++-- test/runner/plugins/test262/util_test262.py | 22 +++++++--- test/runner/starter.py | 20 +++++++++- test/runner/test_js.py | 8 +++- test/runner/utils.py | 26 +++++++++--- 9 files changed, 118 insertions(+), 26 deletions(-) create mode 100644 test/runner/plugins/parser/parser-js-ignored.txt diff --git a/test/parser/js/test-export-named-decl-expected.txt b/test/parser/js/test-export-named-decl-expected.txt index 5f15eaa60..1a9453a55 100644 --- a/test/parser/js/test-export-named-decl-expected.txt +++ b/test/parser/js/test-export-named-decl-expected.txt @@ -571,7 +571,6 @@ } } }, - "decorators": [], "loc": { "start": { "line": 27, diff --git a/test/runner/plugins/hermes/runner_js_hermes.py b/test/runner/plugins/hermes/runner_js_hermes.py index 290a7a645..148ae6494 100644 --- a/test/runner/plugins/hermes/runner_js_hermes.py +++ b/test/runner/plugins/hermes/runner_js_hermes.py @@ -1,5 +1,6 @@ from os import path +from configuration_kind import ConfigurationKind from runner_base import correct_path, get_test_id from runner_file_based import RunnerFileBased from plugins.hermes.test_js_hermes import TestJSHermes @@ -21,11 +22,16 @@ class RunnerJSHermes(RunnerFileBased): ) break - self.util = UtilHermes(self.test_env.args.verbose) + self.util = UtilHermes( + force_download=self.args.force_download, + jit=self.conf_kind == ConfigurationKind.JIT, + jit_preheat_repeats=self.args.jit_preheat_repeats, + verbose=self.test_env.args.verbose + ) self.test_env.util = self.util self.test_root = self.util.generate( - self.build_dir, - args.progress + build_dir=self.build_dir, + show_progress=args.progress ) self.add_directory(self.test_root, "js", []) diff --git a/test/runner/plugins/hermes/util_hermes.py b/test/runner/plugins/hermes/util_hermes.py index a50b0bbd6..fd5f74367 100644 --- a/test/runner/plugins/hermes/util_hermes.py +++ b/test/runner/plugins/hermes/util_hermes.py @@ -1,5 +1,6 @@ import re -from os import getenv +from glob import glob +from os import getenv, path, makedirs import subprocess import utils @@ -10,9 +11,12 @@ HERMES_REVISION = "HERMES_REVISION" class UtilHermes: - def __init__(self, verbose=False): + def __init__(self, force_download: bool, jit: bool, jit_preheat_repeats: int, verbose=False): self.check_expr = re.compile(r"^\s*//\s?(?:CHECK-NEXT|CHECK-LABEL|CHECK):(.+)", re.MULTILINE) + self.force_download = force_download + self.jit = jit + self.jit_preheat_repeats = jit_preheat_repeats self.verbose = verbose self.hermes_url = getenv(HERMES_URL) @@ -22,17 +26,45 @@ class UtilHermes: if self.hermes_revision is None: raise EnvironmentError(f"No {HERMES_REVISION} environment variable set") - def generate(self, build_dir, show_progress, source_path=None): + def generate(self, build_dir, show_progress): + stamp_name = f"hermes-{self.hermes_revision}" + if self.jit and self.jit_preheat_repeats > 1: + stamp_name += f"-jit-{self.jit_preheat_repeats}" return utils.generate( name="hermes", + stamp_name=stamp_name, url=self.hermes_url, revision=self.hermes_revision, build_dir=build_dir, test_subdir="test/hermes", show_progress=show_progress, - source_path=source_path + process_copy=self.process_copy, + force_download=self.force_download ) + def process_copy(self, src_path: str, dst_path: str): + print("Generating tests") + + glob_expression = path.join(src_path, "**/*.js") + files = glob(glob_expression, recursive=True) + + for src_file in files: + dest_file = src_file.replace(src_path, dst_path) + makedirs(path.dirname(dest_file), exist_ok=True) + self.create_file(src_file, dest_file) + + def create_file(self, src_file: str, dest_file: str): + with open(src_file, 'r') as fp: + input_str = fp.read() + + if self.jit and self.jit_preheat_repeats > 1: + out_str = utils.wrap_with_function(input_str, self.jit_preheat_repeats) + else: + out_str = input_str + + with open(dest_file, 'w') as o: + o.write(out_str) + def run_filecheck(self, test_file, actual_output): with open(test_file, 'r') as fp: input_str = fp.read() diff --git a/test/runner/plugins/parser/parser-js-ignored.txt b/test/runner/plugins/parser/parser-js-ignored.txt new file mode 100644 index 000000000..81ec7715c --- /dev/null +++ b/test/runner/plugins/parser/parser-js-ignored.txt @@ -0,0 +1 @@ +parser/js/test-import-meta.js \ No newline at end of file diff --git a/test/runner/plugins/test262/runner_js_test262.py b/test/runner/plugins/test262/runner_js_test262.py index 013869427..f622bb0d4 100644 --- a/test/runner/plugins/test262/runner_js_test262.py +++ b/test/runner/plugins/test262/runner_js_test262.py @@ -1,5 +1,6 @@ from os import path +from configuration_kind import ConfigurationKind from runner_base import correct_path, get_test_id from runner_file_based import RunnerFileBased from plugins.test262.test_js_test262 import TestJSTest262 @@ -19,11 +20,16 @@ class RunnerJSTest262(RunnerFileBased): self.bco_list = correct_path(self.list_root, f"{self.ignored_name_prefix}skiplist-bco.txt") self.bco_tests = self.load_tests_from_lists([self.bco_list]) - self.util = UtilTest262() + self.util = UtilTest262( + force_download=self.args.force_download, + jit=self.conf_kind == ConfigurationKind.JIT, + jit_preheat_repeats=self.args.jit_preheat_repeats + ) + self.test_root = self.util.generate( - self.build_dir, - path.join(self.list_root, "test262harness.js"), - args.progress) + build_dir=self.build_dir, + harness_path=path.join(self.list_root, "test262harness.js"), + show_progress=args.progress) self.test_env.util = self.util self.add_directory(self.test_root, "js", []) diff --git a/test/runner/plugins/test262/util_test262.py b/test/runner/plugins/test262/util_test262.py index 2bd6f20aa..54a6d3bd2 100755 --- a/test/runner/plugins/test262/util_test262.py +++ b/test/runner/plugins/test262/util_test262.py @@ -26,8 +26,11 @@ TEST262_REVISION = "TEST262_REVISION" class UtilTest262: - def __init__(self): + def __init__(self, force_download: bool, jit: bool, jit_preheat_repeats: int): self.async_ok = re.compile(r"Test262:AsyncTestComplete") + self.force_download = force_download + self.jit = jit + self.jit_preheat_repeats = jit_preheat_repeats self.test262_url = getenv(TEST262_URL) self.test262_revision = getenv(TEST262_REVISION) @@ -36,16 +39,20 @@ class UtilTest262: if self.test262_revision is None: raise EnvironmentError(f"No {TEST262_REVISION} environment variable set") - def generate(self, build_dir, harness_path, show_progress, source_path=None): + def generate(self, build_dir, harness_path, show_progress): + stamp_name = f"test262-{self.test262_revision}" + if self.jit and self.jit_preheat_repeats > 1: + stamp_name += f"-jit-{self.jit_preheat_repeats}" return utils.generate( name="test262", + stamp_name=stamp_name, url=self.test262_url, revision=self.test262_revision, build_dir=build_dir, test_subdir="test", show_progress=show_progress, process_copy=lambda src, dst: self.prepare_tests(src, dst, harness_path, path.dirname(src)), - source_path=source_path + force_download=self.force_download ) def prepare_tests(self, src_path, dest_path, harness_path, test262_path): @@ -65,8 +72,7 @@ class UtilTest262: makedirs(path.dirname(dest_file), exist_ok=True) self.create_file(src_file, dest_file, harness, test262_path) - @staticmethod - def create_file(input_file, output_file, harness, test262_dir): + def create_file(self, input_file, output_file, harness, test262_dir): descriptor = Descriptor(input_file) desc = UtilTest262.process_descriptor(descriptor) @@ -82,7 +88,11 @@ class UtilTest262: out_str += "//------------ %s end ------------\n" % include out_str += "\n" - out_str += descriptor.get_content() + if self.jit and self.jit_preheat_repeats > 1: + out_str += utils.wrap_with_function(descriptor.get_content(), self.jit_preheat_repeats) + else: + out_str += descriptor.get_content() + with open(output_file, 'w') as o: o.write(out_str) diff --git a/test/runner/starter.py b/test/runner/starter.py index ee266f1bc..743f5d390 100644 --- a/test/runner/starter.py +++ b/test/runner/starter.py @@ -18,14 +18,18 @@ def is_file(parser, arg): return path.abspath(arg) -def check_timeout(value): +def check_int(value: str, value_name: str) -> int: ivalue = int(value) if ivalue <= 0: - raise argparse.ArgumentTypeError(f"{value} is an invalid timeout value") + raise argparse.ArgumentTypeError(f"{value} is an invalid {value_name} value") return ivalue +def check_timeout(value: str) -> int: + return check_int(value, "timeout") + + def get_args(): parser = argparse.ArgumentParser(description="Regression test runner") parser.add_argument( @@ -51,6 +55,10 @@ def get_args(): '--custom-es2panda', action='store', dest='custom_es2panda_path', type=lambda arg: is_file(parser, arg), default=False, help='custom path to es2panda binary file') + parser.add_argument( + '--force-download', action='store_true', dest='force_download', + default=False, help='force download and prepare test suites') + parser.add_argument( '--test-root', dest='test_root', default=None, type=lambda arg: is_directory(parser, arg), help='directory with test file. If not set the module directory is used') @@ -111,6 +119,14 @@ def get_args(): parser.add_argument( '--jit', action='store_true', dest='jit', default=False, help='use JIT in interpreter') + parser.add_argument( + '--jit-preheat-repeats', action='store', dest='jit_preheat_repeats', + type=lambda arg: check_int(arg, "--jit-preheat-repeats"), default=1, + help='number of code repeat to preheat JIT. Works only with --jit option.') + parser.add_argument( + '--compiler-hotness-threshold', action='store', dest='compiler_hotness_threshold', + type=lambda arg: check_int(arg, "--compiler-hotness-threshold"), default=None, + help='value for ark option --compiler-hotness-threshold. If not set the ark default value is used.') parser.add_argument( '--arm64-compiler-skip', action='store_true', dest='arm64_compiler_skip', default=False, help='use skiplist for tests failing on aarch64 in AOT or JIT mode') diff --git a/test/runner/test_js.py b/test/runner/test_js.py index 96d2b7b98..35f7e2280 100644 --- a/test/runner/test_js.py +++ b/test/runner/test_js.py @@ -85,7 +85,13 @@ class TestJS(Test): ark_flags.extend(["--aot-files", test_an]) if self.test_env.conf_kind == ConfigurationKind.JIT: - ark_flags.extend(['--compiler-enable-jit=true', '--compiler-hotness-threshold=0', '--compiler-check-final=true']) + ark_flags.extend([ + '--compiler-enable-jit=true', + '--compiler-check-final=true']) + if self.test_env.args.compiler_hotness_threshold is not None: + ark_flags.append( + f'--compiler-hotness-threshold={self.test_env.args.compiler_hotness_threshold}' + ) else: ark_flags.extend(['--compiler-enable-jit=false']) diff --git a/test/runner/utils.py b/test/runner/utils.py index 97307ffd3..8191177d5 100644 --- a/test/runner/utils.py +++ b/test/runner/utils.py @@ -2,6 +2,7 @@ from os import makedirs, path, remove import os import shutil import subprocess +from typing import Callable def download(name, git_url, revision, target_path, show_progress=False): @@ -32,17 +33,20 @@ def download(name, git_url, revision, target_path, show_progress=False): remove(archive_file) -def generate(name, url, revision, build_dir, test_subdir="test", show_progress=False, process_copy=None, source_path=None): - dest_path = path.join(build_dir, name) +def generate(name: str, url: str, revision: str, build_dir: str, *, + stamp_name: str = None, test_subdir: str = "test", show_progress: bool = False, + process_copy: Callable[[str, str], None] = None, force_download: bool = False): + stamp_name = f'{name}-{revision}' if not stamp_name else stamp_name + dest_path = path.join(build_dir, stamp_name) makedirs(dest_path, exist_ok=True) - stamp_file = path.join(dest_path, f'{name}-{revision}.stamp') + stamp_file = path.join(dest_path, f'{stamp_name}.stamp') - if path.exists(stamp_file): + if not force_download and path.exists(stamp_file): return dest_path temp_path = path.join(path.sep, 'tmp', name, f'{name}-{revision}') - if not path.exists(temp_path): + if force_download or not path.exists(temp_path): download( name, url, @@ -92,3 +96,15 @@ def write_2_file(file_path, content): def purify(line): return line.strip(" \n").replace(" ", "") + + +def wrap_with_function(code: str, jit_preheat_repeats: int) -> str: + return f""" + function repeat_for_jit() {{ + {code} + }} + + for(let i = 0; i < {jit_preheat_repeats}; i++) {{ + repeat_for_jit(i) + }} + """ -- Gitee