• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4"""
5Copyright (c) 2021 Huawei Device Co., Ltd.
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18Description: Use ark to execute js files
19"""
20
21import argparse
22import os
23import platform
24import json
25import sys
26import signal
27import re
28import fileinput
29import subprocess
30from utils import *
31from config import *
32import mix_compile
33
34
35def parse_args():
36    parser = argparse.ArgumentParser()
37    parser.add_argument('--ark-tool',
38                        default=DEFAULT_ARK_TOOL,
39                        required=False,
40                        help="ark's binary tool")
41    parser.add_argument('--ark-aot', action='store_true',
42                        required=False,
43                        help="Run test262 with aot")
44    parser.add_argument('--ark-aot-tool',
45                        default=DEFAULT_ARK_AOT_TOOL,
46                        required=False,
47                        help="ark's aot tool")
48    parser.add_argument("--libs-dir",
49                        default=DEFAULT_LIBS_DIR,
50                        required=False,
51                        help="The path collection of dependent so has been divided by':'")
52    parser.add_argument("--js-file",
53                        required=True,
54                        help="js file")
55    parser.add_argument("--stub-file",
56                        default=DEFAULT_STUB_FILE,
57                        required=False,
58                        help="stub file")
59    parser.add_argument('--ark-frontend',
60                        default=DEFAULT_ARK_FRONTEND,
61                        required=False,
62                        nargs='?', choices=ARK_FRONTEND_LIST, type=str,
63                        help="Choose one of them")
64    parser.add_argument('--ark-frontend-binary',
65                        default=DEFAULT_ARK_FRONTEND_BINARY,
66                        required=False,
67                        help="ark frontend conversion binary tool")
68    parser.add_argument('--icu-data-path',
69                        default=DEFAULT_ICU_PATH,
70                        required=False,
71                        help="ark frontend conversion binary tool")
72    parser.add_argument('--ark-arch',
73                        default=DEFAULT_ARK_ARCH,
74                        required=False,
75                        nargs='?', choices=ARK_ARCH_LIST, type=str,
76                        help="Choose one of them")
77    parser.add_argument('--ark-arch-root',
78                        default=DEFAULT_ARK_ARCH,
79                        required=False,
80                        help="the root path for qemu-aarch64 or qemu-arm")
81    parser.add_argument('--opt-level',
82                        default=DEFAULT_OPT_LEVEL,
83                        required=False,
84                        help="the opt level for es2abc")
85    parser.add_argument('--es2abc-thread-count',
86                        default=DEFAULT_ES2ABC_THREAD_COUNT,
87                        required=False,
88                        help="the thread count for es2abc")
89    parser.add_argument('--merge-abc-binary',
90                        default=DEFAULT_MERGE_ABC_BINARY,
91                        required=False,
92                        help="frontend merge abc binary tool")
93    parser.add_argument('--merge-abc-mode',
94                        default=DEFAULT_MERGE_ABC_MODE,
95                        required=False,
96                        help="run test for merge abc mode")
97    parser.add_argument('--product-name',
98                        default=DEFAULT_PRODUCT_NAME,
99                        required=False,
100                        help="ark's product name")
101    parser.add_argument('--run-pgo', action='store_true',
102                        required=False,
103                        help="Run test262 with aot pgo")
104    parser.add_argument('--enable-litecg', action='store_true',
105                        required=False,
106                        help="Run test262 with aot litecg enabled")
107    parser.add_argument('--run-jit', action='store_true',
108                        required=False,
109                        help="Run test262 with JIT")
110    parser.add_argument('--run-baseline-jit', action='store_true',
111                        required=False,
112                        help="Run test262 with baseline JIT")
113    parser.add_argument('--abc2program', action='store_true',
114                        help="Use abc2prog to generate abc, aot or pgo is not supported yet under this option")
115    parser.add_argument('--disable-force-gc', action='store_true',
116                        help="Run test262 with close force-gc")
117    parser.add_argument('--enable-arkguard', action='store_true',
118                        required=False,
119                        help="enable arkguard for 262 tests")
120    arguments = parser.parse_args()
121    return arguments
122
123
124ICU_PATH = DEFAULT_ICU_PATH
125if platform.system() == "Windows":
126    ICU_PATH = ICU_PATH.replace("/", "\\")
127ARK_TOOL = DEFAULT_ARK_TOOL
128LIBS_DIR = DEFAULT_LIBS_DIR
129ARK_AOT_TOOL = DEFAULT_ARK_AOT_TOOL
130ARK_FRONTEND = DEFAULT_ARK_FRONTEND
131ARK_FRONTEND_BINARY = DEFAULT_ARK_FRONTEND_BINARY
132ARK_ARCH = DEFAULT_ARK_ARCH
133PROTO_BIN_SUFFIX = "protoBin"
134
135
136class ArkProgram():
137    def __init__(self, args):
138        self.args = args
139        self.ark_tool = ARK_TOOL
140        self.ark_aot = False
141        self.run_pgo = False
142        self.enable_litecg = False
143        self.disable_force_gc = False
144        self.run_jit = False
145        self.run_baseline_jit = False
146        self.ark_aot_tool = ARK_AOT_TOOL
147        self.libs_dir = LIBS_DIR
148        self.ark_frontend = ARK_FRONTEND
149        self.ark_frontend_binary = ARK_FRONTEND_BINARY
150        self.icu_data_path = ICU_PATH
151        self.module_list = []
152        self.dynamicImport_list = []
153        self.js_file = ""
154        self.stub_file = ""
155        self.module = False
156        self.abc_file = ""
157        self.arch = ARK_ARCH
158        self.arch_root = ""
159        self.opt_level = DEFAULT_OPT_LEVEL
160        self.es2abc_thread_count = DEFAULT_ES2ABC_THREAD_COUNT
161        self.merge_abc_binary = DEFAULT_MERGE_ABC_BINARY
162        self.merge_abc_mode = DEFAULT_MERGE_ABC_MODE
163        self.abc2program = False
164        # when enabling abc2program, may generate a list of abc files
165        self.abc_outputs = []
166        self.enable_arkguard = False
167
168    def proce_parameters(self):
169        if self.args.ark_tool:
170            self.ark_tool = self.args.ark_tool
171
172        if self.args.ark_aot:
173            self.ark_aot = self.args.ark_aot
174
175        if self.args.run_pgo:
176            self.run_pgo = self.args.run_pgo
177
178        if self.args.enable_litecg:
179            self.enable_litecg = self.args.enable_litecg
180
181        if self.args.disable_force_gc:
182            self.disable_force_gc = self.args.disable_force_gc
183
184        if self.args.run_jit:
185            self.run_jit = self.args.run_jit
186
187        if self.args.run_baseline_jit:
188            self.run_baseline_jit = self.args.run_baseline_jit
189
190        if self.args.ark_aot_tool:
191            self.ark_aot_tool = self.args.ark_aot_tool
192
193        if self.args.ark_frontend_binary:
194            self.ark_frontend_binary = self.args.ark_frontend_binary
195        if self.args.icu_data_path:
196            self.icu_data_path = self.args.icu_data_path
197        if self.args.libs_dir:
198            self.libs_dir = self.args.libs_dir
199
200        if self.args.ark_frontend:
201            self.ark_frontend = self.args.ark_frontend
202
203        if self.args.opt_level:
204            self.opt_level = self.args.opt_level
205
206        if self.args.es2abc_thread_count:
207            self.es2abc_thread_count = self.args.es2abc_thread_count
208
209        if self.args.merge_abc_binary:
210            self.merge_abc_binary = self.args.merge_abc_binary
211
212        if self.args.merge_abc_mode:
213            self.merge_abc_mode = self.args.merge_abc_mode
214
215        if self.args.abc2program:
216            self.abc2program = self.args.abc2program
217
218        self.enable_arkguard = self.args.enable_arkguard
219
220        self.module_list = MODULE_LIST
221
222        self.dynamicImport_list = DYNAMIC_IMPORT_LIST
223
224        self.js_file = self.args.js_file
225
226        self.stub_file = self.args.stub_file
227
228        self.arch = self.args.ark_arch
229
230        self.arch_root = self.args.ark_arch_root
231
232    def check_compile_mode(self, file):
233        with open(file, 'r', encoding='utf-8') as check_file:
234            content_file = check_file.read()
235            module_pattern = '((?:export|import)\s+(?:{[\s\S]+}|\*))|'
236            module_pattern += '(export\s+(?:let|const|var|function|class|default))|'
237            module_pattern += '(import\s+[\'\"].+[\'\"])'
238            module_mode_list = re.findall(module_pattern, content_file)
239
240            for module_mode in list(set(module_mode_list)):
241                if len(module_mode[0]) != 0 or len(module_mode[1]) != 0 or len(module_mode[2]) != 0:
242                    return True
243
244        if "flags: [module]" in content_file or "/language/module-code/" in self.js_file:
245            return True
246
247        return False
248
249    def get_all_skip_force_gc_tests(self):
250        SKIP_FORCE_GC_LIST_FILES.append(TS2ABC_SKIP_FORCE_GC_LIST_FILE)
251
252        for file in SKIP_FORCE_GC_LIST_FILES:
253            with open(file) as jsonfile:
254                json_data = json.load(jsonfile)
255                for key in json_data:
256                    FORCE_GC_SKIP_TESTS.extend(key["files"])
257
258    def gen_dependency_proto(self, dependency):
259        cmd_args = []
260        output_file = os.path.splitext(dependency.replace(DATA_DIR, BASE_OUT_DIR))[0]
261        output_abc = f"{output_file}{ABC_EXT}"
262        frontend_tool = self.ark_frontend_binary
263        merge_abc_binary = self.args.merge_abc_binary
264        merge_abc_mode = self.merge_abc_mode
265        compile_as_module = self.check_compile_mode(dependency)
266
267        if self.ark_frontend == ARK_FRONTEND_LIST[0]:
268            if merge_abc_mode != "0":
269                cmd_args = ['node', '--expose-gc', frontend_tool, dependency,
270                            '--output-proto', '--merge-abc']
271            else:
272                # for testing no-record-name abc
273                cmd_args = ['node', '--expose-gc', frontend_tool, dependency,
274                            '-o', output_abc]
275            if compile_as_module:
276                mod_opt_index = 6
277                cmd_args.insert(mod_opt_index, "--modules")
278        elif self.ark_frontend == ARK_FRONTEND_LIST[1]:
279            if merge_abc_mode != "0":
280                proto_bin_file = output_file + "." + PROTO_BIN_SUFFIX
281                cmd_args = [frontend_tool, dependency, '--outputProto',
282                            proto_bin_file, '--merge-abc']
283            else:
284                # for testing no-record-name abc
285                cmd_args = [frontend_tool, dependency, '--output', output_abc]
286            if compile_as_module:
287                mod_opt_index = 4
288                cmd_args.insert(mod_opt_index, "--module")
289        proc = subprocess.Popen(cmd_args)
290        proc.wait()
291
292    def gen_apart_abc(self, dependencies):
293        merge_abc_binary = self.args.merge_abc_binary
294        retcode = 0
295        for dependency in list(set(dependencies)):
296            cmd_args = []
297            output_file = os.path.splitext(dependency.replace(DATA_DIR, BASE_OUT_DIR))[0]
298            output_abc = os.path.basename(f"{output_file}{ABC_EXT}")
299            file_dir = os.path.split(self.js_file)[0]
300            is_apart_abc_existed = os.path.exists(file_dir + "/" + output_abc)
301            dependency_file_prefix = os.path.basename(dependency)[:-3]
302            dependency_bin_file = '%s/%s.%s' % (file_dir,
303                                                dependency_file_prefix, PROTO_BIN_SUFFIX)
304            cmd_args = [merge_abc_binary, '--input', dependency_bin_file,
305                        '--suffix', PROTO_BIN_SUFFIX, '--outputFilePath',
306                        file_dir, '--output', output_abc]
307            if not is_apart_abc_existed:
308                retcode = exec_command(cmd_args)
309        return retcode
310
311    def gen_merged_abc(self, dependencies, file_name_pre, proto_bin_file):
312        merge_abc_binary = self.args.merge_abc_binary
313        file_dir = os.path.split(self.js_file)[0]
314        proto_abc_file = ".".join([os.path.splitext(os.path.basename(self.js_file))[0], "abc"])
315        generate_merged_abc = True
316        # collect protoBin file into new-made testcase dir
317        if (len(dependencies) != 0):
318            if os.path.exists(file_name_pre):
319                subprocess.run(['rm', '-rf', file_name_pre])
320            subprocess.run(['mkdir', file_name_pre])
321
322            for dependency in list(set(dependencies)):
323                dependency_file_prefix = os.path.basename(dependency)[:-3]
324                dependency_bin_file = '%s/%s.%s' % (file_dir,
325                                                    dependency_file_prefix, PROTO_BIN_SUFFIX)
326                # test262 report syntax error cases
327                if not os.path.exists(dependency_bin_file):
328                    generate_merged_abc = False
329                else:
330                    subprocess.run(['cp', dependency_bin_file, file_name_pre])
331
332            if not os.path.exists(proto_bin_file):
333                generate_merged_abc = False
334            else:
335                subprocess.run(['cp', proto_bin_file, file_name_pre])
336
337        if (len(dependencies) != 0) and generate_merged_abc:
338            # module test262 cases
339            cmd_args = [merge_abc_binary, '--input', file_name_pre,
340                        '--suffix', PROTO_BIN_SUFFIX, '--outputFilePath',
341                        file_dir, '--output', proto_abc_file]
342            self.abc_file = f'{file_name_pre}.abc'
343            return exec_command(cmd_args)
344        elif os.path.exists(proto_bin_file):
345            cmd_args = [merge_abc_binary, '--input', proto_bin_file,
346                        '--suffix', PROTO_BIN_SUFFIX, '--outputFilePath',
347                        file_dir, '--output', proto_abc_file]
348            self.abc_file = f'{file_name_pre}.abc'
349            return exec_command(cmd_args)
350        return 0
351
352    def gen_abc_for_merge_abc_mode(self, js_file, dependencies):
353        file_name_pre = os.path.splitext(js_file)[0]
354        proto_bin_file = file_name_pre + "." + PROTO_BIN_SUFFIX
355
356        if "dynamic-import" in js_file:
357            return self.gen_apart_abc(dependencies)
358        else:
359            return self.gen_merged_abc(dependencies, file_name_pre, proto_bin_file)
360
361    def gen_abc_for_script_mode(self, cmd_args, retcode):
362        retcode = exec_command(cmd_args)
363        if retcode == 1:
364            return retcode
365        self.abc_cmd = cmd_args
366        return retcode
367
368    def gen_abc_for_dynamic_import(self, js_file, retcode):
369        file_name_pre = os.path.splitext(js_file)[0]
370        out_file = f"{file_name_pre}{ABC_EXT}"
371        proto_bin_file = file_name_pre + "." + PROTO_BIN_SUFFIX
372        merge_abc_binary = self.args.merge_abc_binary
373
374        if ("dynamic-import" in js_file and not os.path.exists(out_file)):
375            file_dir = os.path.split(self.js_file)[0]
376            proto_abc_file = ".".join([os.path.splitext(os.path.basename(self.js_file))[0], "abc"])
377            cmd_args = [merge_abc_binary, '--input', proto_bin_file,
378                        '--suffix', PROTO_BIN_SUFFIX, '--outputFilePath',
379                        file_dir, '--output', proto_abc_file]
380            retcode = exec_command(cmd_args)
381            if retcode == 1:
382                return retcode
383            self.abc_cmd = cmd_args
384            return retcode
385
386    def get_abc_from_import_statement(self, js_file):
387        file_name_pre = os.path.splitext(js_file)[0]
388        out_file = f"{file_name_pre}{ABC_EXT}"
389
390        self.abc_file = os.path.abspath(out_file)
391        js_dir = os.path.dirname(js_file)
392        for line in fileinput.input(js_file):
393            import_line = re.findall(r"^(?:ex|im)port.*\.js", line)
394            if len(import_line):
395                import_file = re.findall(r"['\"].*\.js", import_line[0])
396                if len(import_file):
397                    abc_file = import_file[0][1:].replace(".js", ABC_EXT)
398                    abc_file = os.path.abspath(f'{js_dir}/{abc_file}')
399                    if self.abc_file.find(abc_file) < 0:
400                        self.abc_file += f':{abc_file}'
401
402    def gen_command(self, js_file, compile_as_module):
403        cmd_args = []
404        mod_opt_index = 0
405        frontend_tool = self.ark_frontend_binary
406        file_name_pre = os.path.splitext(js_file)[0]
407        merge_abc_mode = self.merge_abc_mode
408        proto_bin_file = file_name_pre + "." + PROTO_BIN_SUFFIX
409        out_file = f"{file_name_pre}{ABC_EXT}"
410
411        if self.ark_frontend == ARK_FRONTEND_LIST[0]:
412            mod_opt_index = 3
413            if merge_abc_mode != "0":
414                cmd_args = ['node', '--expose-gc', frontend_tool, js_file,
415                            '--output-proto', '--merge-abc']
416            else:
417                # for testing no-record-name abc
418                cmd_args = ['node', '--expose-gc', frontend_tool, js_file,
419                            '-o', out_file]
420            if compile_as_module:
421                cmd_args.insert(mod_opt_index, "-m")
422                self.module = True
423        elif self.ark_frontend == ARK_FRONTEND_LIST[1]:
424            mod_opt_index = 1
425            if merge_abc_mode != "0":
426                # '--merge-abc' is added due to 'merge-abc' is not opened as default in es2abc, should be removed later
427                cmd_args = [frontend_tool, '--function-threads=' +
428                            str(self.es2abc_thread_count), '--outputProto',
429                            proto_bin_file, js_file, '--merge-abc', '--opt-level=' + str(self.opt_level)]
430            else:
431                # for testing no-record-name abc
432                cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level),
433                            '--function-threads=' +
434                            str(self.es2abc_thread_count), '--output',
435                            out_file, js_file]
436            if compile_as_module:
437                cmd_args.insert(mod_opt_index, "--module")
438                self.module = True
439
440        return cmd_args
441
442    def gen_dependencies_proto(self, js_file):
443        file_dir = os.path.split(js_file)[0]
444        compile_as_module = False
445        dependencies = []
446
447        if ("dynamic-import" in js_file):
448            search_dir = os.path.dirname(js_file)
449        else:
450            search_dir = os.path.dirname(js_file.replace(BASE_OUT_DIR, DATA_DIR))
451
452        dependencies = collect_module_dependencies(js_file, search_dir, [])
453        compile_as_module = self.check_compile_mode(js_file)
454
455        if (self.ark_frontend == ARK_FRONTEND_LIST[1]):
456            if list(set(dependencies)):
457                for dependency in list(set(dependencies)):
458                    dependency_file = os.path.basename(dependency)
459                    dependency_name = os.path.splitext(dependency_file)[0]
460                    out_dependency_pre = '%s/%s' % (file_dir, dependency_name)
461                    out_dependency_proto = f"{out_dependency_pre}.protoBin"
462                    is_dependency_proto_existed = os.path.exists(out_dependency_proto)
463                    if not is_dependency_proto_existed:
464                        self.gen_dependency_proto(dependency)
465
466        return compile_as_module, dependencies
467
468    def gen_abc_for_mix_compile_mode(self, dependencies, out_file):
469        record_names = set()
470        files_info_list = []
471        # In some cases of circular reference, the js file will be from BASE_OUT_DIR, remove it
472        dependencies = [os.path.abspath(dependency) for dependency in dependencies]
473        dependencies.insert(0, os.path.abspath(self.js_file))
474        for dependency in dependencies:
475            record_name = os.path.splitext(os.path.basename(dependency))[0]
476            if record_name in record_names:
477                continue
478
479            record_names.add(record_name)
480            compile_mode = 'esm' if self.check_compile_mode(dependency) else 'script'
481            files_info_list.append(f"{dependency};{record_name};{compile_mode};xxx;yyy\n")
482
483        mix_compiler = mix_compile.MixCompiler(out_file, files_info_list, self.opt_level,
484                                               self.es2abc_thread_count, self.es2abc_thread_count,
485                                               self.es2abc_thread_count, self.ark_frontend_binary)
486
487        retcode = mix_compiler.mix_compile()
488        self.abc_outputs = mix_compiler.abc_outputs
489        return retcode
490
491    def gen_abc(self):
492        js_file = self.js_file
493        file_name_pre = os.path.splitext(js_file)[0]
494        file_name = os.path.basename(js_file)
495        file_dir = os.path.split(js_file)[0]
496        out_file = f"{file_name_pre}{ABC_EXT}"
497        out_proto = f"{file_name_pre}.proto"
498        proto_bin_file = file_name_pre + "." + PROTO_BIN_SUFFIX
499        self.abc_file = out_file
500        mod_opt_index = 0
501        compile_as_module = False
502        cmd_args = []
503        dependency_cmd_args = []
504        frontend_tool = self.ark_frontend_binary
505        merge_abc_mode = self.merge_abc_mode
506        dependencies = []
507        merge_abc_binary = self.args.merge_abc_binary
508        retcode = 0
509
510        # generate the dependencies' proto when ark_frontend is [es2panda]
511        if (file_name in self.module_list or file_name in self.dynamicImport_list):
512            compile_as_module, dependencies = self.gen_dependencies_proto(js_file)
513
514        if self.abc2program:
515            return self.gen_abc_for_mix_compile_mode(dependencies, out_file)
516
517        # generate execution command
518        cmd_args = self.gen_command(js_file, compile_as_module)
519
520        # get abc file list from import statement
521        if merge_abc_mode == "0" and self.ark_aot and self.module:
522            self.get_abc_from_import_statement(js_file)
523
524        # generate abc file by script mode
525        if not os.path.exists(out_proto):
526            retcode = self.gen_abc_for_script_mode(cmd_args, retcode)
527            if retcode == 1:
528                return retcode
529
530        # generate abc file by script mode for dynamic-import
531        if self.ark_frontend == ARK_FRONTEND_LIST[1]:
532            retcode = self.gen_abc_for_dynamic_import(js_file, retcode)
533            if retcode == 1:
534                return retcode
535
536        # generate merged abc file
537        if merge_abc_mode != "0":
538            self.gen_abc_for_merge_abc_mode(js_file, dependencies)
539
540        return retcode
541
542    def execute_arkguard(self):
543        js_file = self.js_file
544        js_file_allpath = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../', js_file)
545        cmd_args = ['node', '--no-warnings',
546                    '--loader=ts-node/esm',
547                    './src/cli/SecHarmony.ts',
548                    js_file_allpath,
549                    '--config-path',
550                    './test/test262/test262Config.json',
551                    '--inplace']
552        arkguard_path = os.getcwd() + '/arkguard'
553        retcode = exec_command(cmd_args, custom_cwd = arkguard_path)
554
555    def compile_aot(self):
556        os.environ["LD_LIBRARY_PATH"] = self.libs_dir
557        file_name_pre = os.path.splitext(self.js_file)[0]
558        icu_path = f"--icu-data-path={self.icu_data_path}"
559        cmd_args = []
560        if self.run_pgo:
561            if self.arch == ARK_ARCH_LIST[1]:
562                qemu_tool = "qemu-aarch64"
563                qemu_arg1 = "-L"
564                qemu_arg2 = self.arch_root
565                cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_aot_tool,
566                            icu_path, f'--compiler-target-triple=aarch64-unknown-linux-gnu']
567            elif self.arch == ARK_ARCH_LIST[2]:
568                cmd_args = [self.ark_aot_tool, icu_path, f'--compiler-target-triple=arm-unknown-linux-gnu']
569            elif self.arch == ARK_ARCH_LIST[0]:
570                cmd_args = [self.ark_aot_tool, icu_path]
571            cmd_args.append("--compiler-opt-loop-peeling=true")
572            cmd_args.append("--compiler-fast-compile=false")
573            cmd_args.append("--compiler-opt-track-field=true")
574            cmd_args.append("--compiler-opt-inlining=true")
575            cmd_args.append("--compiler-max-inline-bytecodes=45")
576            cmd_args.append("--compiler-opt-level=2")
577            if self.stub_file != "":
578                cmd_args.append(f"--stub-file={self.stub_file}")
579            if self.disable_force_gc:
580                cmd_args.append(f"--enable-force-gc=false")
581            cmd_args.append(f'--compiler-pgo-profiler-path={file_name_pre}.ap')
582            cmd_args.append(f'--aot-file={file_name_pre}')
583            cmd_args.append(self.abc_file)
584        else:
585            if self.arch == ARK_ARCH_LIST[1]:
586                cmd_args = [self.ark_aot_tool, icu_path,
587                            f'--compiler-target-triple=aarch64-unknown-linux-gnu',
588                            f'--aot-file={file_name_pre}',
589                            self.abc_file]
590            elif self.arch == ARK_ARCH_LIST[2]:
591                cmd_args = [self.ark_aot_tool, icu_path,
592                            f'--compiler-target-triple=arm-unknown-linux-gnu',
593                            f'--aot-file={file_name_pre}',
594                            self.abc_file]
595            elif self.arch == ARK_ARCH_LIST[0]:
596                cmd_args = [self.ark_aot_tool, icu_path,
597                            f'--aot-file={file_name_pre}',
598                            self.abc_file]
599        if self.enable_litecg:
600            cmd_args.insert(-1, "--compiler-enable-litecg=true")
601        retcode = exec_command(cmd_args, 180000)
602        if retcode:
603            print_command(self.abc_cmd)
604            print_command(cmd_args)
605
606    def execute_aot(self):
607        unforce_gc = False
608        os.environ["LD_LIBRARY_PATH"] = self.libs_dir
609        file_name_pre = os.path.splitext(self.js_file)[0]
610        cmd_args = []
611        icu_path = f"--icu-data-path={self.icu_data_path}"
612        if self.arch == ARK_ARCH_LIST[1]:
613            qemu_tool = "qemu-aarch64"
614            qemu_arg1 = "-L"
615            qemu_arg2 = self.arch_root
616            cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool,
617                        icu_path,
618                        f'--aot-file={file_name_pre}',
619                        f'{file_name_pre}.abc']
620        elif self.arch == ARK_ARCH_LIST[2]:
621            qemu_tool = "qemu-arm"
622            qemu_arg1 = "-L"
623            qemu_arg2 = self.arch_root
624            cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool,
625                        icu_path,
626                        f'--aot-file={file_name_pre}',
627                        f'{file_name_pre}.abc']
628        elif self.arch == ARK_ARCH_LIST[0]:
629            if file_name_pre in FORCE_GC_SKIP_TESTS:
630                unforce_gc = True
631            asm_arg1 = "--enable-force-gc=true"
632            if unforce_gc or self.disable_force_gc:
633                asm_arg1 = "--enable-force-gc=false"
634            cmd_args = [self.ark_tool, icu_path, asm_arg1,
635                        f'--aot-file={file_name_pre}',
636                        f'{file_name_pre}.abc']
637        record_name = os.path.splitext(os.path.split(self.js_file)[1])[0]
638        cmd_args.insert(-1, f'--entry-point={record_name}')
639        if self.stub_file != "":
640            cmd_args.insert(-1, f'--stub-file={self.stub_file}')
641        retcode = exec_command(cmd_args)
642        if retcode:
643            print_command(cmd_args)
644        return retcode
645
646    def execute_abc2program_outputs(self, cmd_args):
647        retcode = 0
648        for abc in self.abc_outputs:
649            abc = get_formated_path(abc)
650            cmd_args[-1] = abc
651            retcode = exec_command(cmd_args)
652            if retcode:
653                print_command(cmd_args)
654                return retcode
655        return retcode
656
657    def execute(self):
658        icu_path = f"--icu-data-path={self.icu_data_path}"
659        unforce_gc = False
660        if platform.system() == "Windows":
661            # add env path for cmd/powershell execute
662            libs_dir = self.libs_dir.replace(":", ";")
663            libs_dir = libs_dir.replace("/", "\\")
664            os.environ["PATH"] = libs_dir + ";" + os.environ["PATH"]
665        elif platform.system() == "Linux":
666            os.environ["LD_LIBRARY_PATH"] = self.libs_dir
667        else:
668            sys.exit(f" test262 on {platform.system()} not supported")
669
670        file_name_pre = get_formated_path(os.path.splitext(self.js_file)[0])
671        cmd_args = []
672        if self.arch == ARK_ARCH_LIST[1]:
673            qemu_tool = "qemu-aarch64"
674            qemu_arg1 = "-L"
675            qemu_arg2 = self.arch_root
676            cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool,
677                        icu_path,
678                        f'{file_name_pre}.abc']
679            if self.run_jit or self.run_baseline_jit:
680                cmd_args.insert(-1, f'--compiler-target-triple=aarch64-unknown-linux-gnu')
681                cmd_args.insert(-1, f'--open-ark-tools=true')
682            if self.run_baseline_jit:
683                cmd_args.insert(-1, f'--test-assert=true')
684        elif self.arch == ARK_ARCH_LIST[2]:
685            qemu_tool = "qemu-arm"
686            qemu_arg1 = "-L"
687            qemu_arg2 = self.arch_root
688            cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool,
689                        icu_path,
690                        f'{file_name_pre}.abc']
691        elif self.arch == ARK_ARCH_LIST[0]:
692            if file_name_pre in FORCE_GC_SKIP_TESTS:
693                unforce_gc = True
694            asm_arg1 = "--enable-force-gc=true"
695            if unforce_gc or self.disable_force_gc:
696                asm_arg1 = "--enable-force-gc=false"
697            cmd_args = [self.ark_tool, icu_path, asm_arg1,
698                        f'{file_name_pre}.abc']
699
700        record_name = os.path.splitext(os.path.split(self.js_file)[1])[0]
701        cmd_args.insert(-1, f'--entry-point={record_name}')
702        if self.run_jit:
703            cmd_args.insert(-1, f'--compiler-enable-litecg=true')
704            cmd_args.insert(-1, f'--compiler-enable-jit=true --log-debug=jit')
705        if self.run_baseline_jit:
706            cmd_args.insert(-1, f'--compiler-enable-baselinejit=true')
707            cmd_args.insert(-1, f'--compiler-force-baselinejit-compile-main=true')
708        if self.stub_file != "":
709            cmd_args.insert(-1, f"--stub-file={self.stub_file}")
710        retcode = 0
711        if self.abc2program:
712            retcode = self.execute_abc2program_outputs(cmd_args)
713        else:
714            retcode = exec_command(cmd_args)
715            if retcode:
716                print_command(cmd_args)
717        return retcode
718
719    def run_generator_ap(self):
720        icu_path = f"--icu-data-path={self.icu_data_path}"
721        os.environ["LD_LIBRARY_PATH"] = self.libs_dir
722        file_name_pre = os.path.splitext(self.js_file)[0]
723        record_name = os.path.splitext(os.path.split(self.js_file)[1])[0]
724        if self.arch == ARK_ARCH_LIST[1]:
725            qemu_tool = "qemu-aarch64"
726            qemu_arg1 = "-L"
727            qemu_arg2 = self.arch_root
728            cmd_args = [qemu_tool, qemu_arg1, qemu_arg2, self.ark_tool,
729                        icu_path,
730                        "--log-level=error",
731                        "--enable-pgo-profiler=true",
732                        "--compiler-opt-inlining=true",
733                        f'--compiler-pgo-profiler-path={file_name_pre}.ap',
734                        "--asm-interpreter=true",
735                        f'--entry-point={record_name}']
736        else:
737            cmd_args = [self.ark_tool, icu_path,
738                        "--log-level=error",
739                        "--enable-pgo-profiler=true",
740                        "--compiler-opt-inlining=true",
741                        f'--compiler-pgo-profiler-path={file_name_pre}.ap',
742                        "--asm-interpreter=true",
743                        f'--entry-point={record_name}']
744        if self.stub_file != "":
745            cmd_args.append(f"--stub-file={self.stub_file}")
746        if self.disable_force_gc:
747            cmd_args.append(f"--enable-force-gc=false")
748        cmd_args.append(f'{file_name_pre}.abc')
749        return_code = exec_command(cmd_args)
750        if return_code:
751            print_command(cmd_args)
752        return return_code
753
754    def is_legal_frontend(self):
755        if self.ark_frontend not in ARK_FRONTEND_LIST:
756            sys.stderr.write("Wrong ark front-end option")
757            return False
758        return True
759
760    def execute_ark(self):
761        self.proce_parameters()
762        self.get_all_skip_force_gc_tests()
763        if not self.is_legal_frontend():
764            return
765        if self.enable_arkguard:
766            self.execute_arkguard()
767        if self.gen_abc():
768            return
769        if self.run_pgo:
770            self.run_generator_ap()
771        if self.ark_aot:
772            self.compile_aot()
773            self.execute_aot()
774        else:
775            self.execute()
776
777
778def main():
779    args = parse_args()
780
781    ark = ArkProgram(args)
782    ark.execute_ark()
783
784
785if __name__ == "__main__":
786    sys.exit(main())
787