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