13af6ab5fSopenharmony_ci#!/usr/bin/env python3
23af6ab5fSopenharmony_ci# -*- coding: utf-8 -*-
33af6ab5fSopenharmony_ci#
43af6ab5fSopenharmony_ci# Copyright (c) 2024 Huawei Device Co., Ltd.
53af6ab5fSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
63af6ab5fSopenharmony_ci# you may not use this file except in compliance with the License.
73af6ab5fSopenharmony_ci# You may obtain a copy of the License at
83af6ab5fSopenharmony_ci#
93af6ab5fSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0
103af6ab5fSopenharmony_ci#
113af6ab5fSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
123af6ab5fSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
133af6ab5fSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
143af6ab5fSopenharmony_ci# See the License for the specific language governing permissions and
153af6ab5fSopenharmony_ci# limitations under the License.
163af6ab5fSopenharmony_ci
173af6ab5fSopenharmony_cifrom abc import ABC, abstractmethod
183af6ab5fSopenharmony_ciimport argparse
193af6ab5fSopenharmony_ciimport glob
203af6ab5fSopenharmony_ciimport json
213af6ab5fSopenharmony_ciimport os
223af6ab5fSopenharmony_ciimport re
233af6ab5fSopenharmony_ciimport shutil
243af6ab5fSopenharmony_ciimport stat
253af6ab5fSopenharmony_ciimport subprocess
263af6ab5fSopenharmony_ciimport sys
273af6ab5fSopenharmony_ciimport threading
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_ciSUCCESS_STATUS = 0
303af6ab5fSopenharmony_ciCRASH_STATUS = -1
313af6ab5fSopenharmony_ciTIMEOUT_STATUS = -2
323af6ab5fSopenharmony_ci
333af6ab5fSopenharmony_ciWORKLOAD_URL = 'https://gitee.com/xliu-huanwei/ark-workload.git'
343af6ab5fSopenharmony_ciBENCHMARK_PATH = '../benchmark'
353af6ab5fSopenharmony_ciSKIP_TEST = 'skip_tests.json'
363af6ab5fSopenharmony_ciDISCREPANCY_REPORT = 'discrepancy_report'
373af6ab5fSopenharmony_ciHTML_CONTENT = \
383af6ab5fSopenharmony_ci"""
393af6ab5fSopenharmony_ci<!DOCTYPE html>
403af6ab5fSopenharmony_ci<html>
413af6ab5fSopenharmony_ci<head>
423af6ab5fSopenharmony_ci    <title>Instruction Discrepancy Report</title>
433af6ab5fSopenharmony_ci    <style>
443af6ab5fSopenharmony_ci        table {
453af6ab5fSopenharmony_ci            width: 50%;
463af6ab5fSopenharmony_ci            border-collapse: collapse;
473af6ab5fSopenharmony_ci            margin: auto;
483af6ab5fSopenharmony_ci        }
493af6ab5fSopenharmony_ci        th, td {
503af6ab5fSopenharmony_ci            padding: 8px;
513af6ab5fSopenharmony_ci            text-align: center;
523af6ab5fSopenharmony_ci            border: 1px solid black;
533af6ab5fSopenharmony_ci            white-space: nowrap;
543af6ab5fSopenharmony_ci        }
553af6ab5fSopenharmony_ci        th:nth-child(2), td:nth-child(2) {
563af6ab5fSopenharmony_ci            text-align: left;
573af6ab5fSopenharmony_ci        }
583af6ab5fSopenharmony_ci        h1 {
593af6ab5fSopenharmony_ci            text-align: center;
603af6ab5fSopenharmony_ci        }
613af6ab5fSopenharmony_ci    </style>
623af6ab5fSopenharmony_ci</head>
633af6ab5fSopenharmony_ci<body>
643af6ab5fSopenharmony_ci    <h1>Instruction Discrepancy Report</h1>
653af6ab5fSopenharmony_ci    <table>
663af6ab5fSopenharmony_ci        <tr>
673af6ab5fSopenharmony_ci            <th>No</th>
683af6ab5fSopenharmony_ci            <th>Case Path</th>
693af6ab5fSopenharmony_ci            <th>es2abc Instruction Number</th>
703af6ab5fSopenharmony_ci            <th>v8 Instruction Number</th>
713af6ab5fSopenharmony_ci            <th>es2abc/v8 Ratio</th>
723af6ab5fSopenharmony_ci        </tr>
733af6ab5fSopenharmony_ci"""
743af6ab5fSopenharmony_ci
753af6ab5fSopenharmony_ci
763af6ab5fSopenharmony_cidef is_file(parser, arg):
773af6ab5fSopenharmony_ci    if not os.path.isfile(arg):
783af6ab5fSopenharmony_ci        parser.error(f'[ERROR]: The file "{arg}" does not exist!')
793af6ab5fSopenharmony_ci    return os.path.abspath(arg)
803af6ab5fSopenharmony_ci
813af6ab5fSopenharmony_ci
823af6ab5fSopenharmony_cidef is_directory(parser, arg):
833af6ab5fSopenharmony_ci    if not os.path.isdir(arg):
843af6ab5fSopenharmony_ci        parser.error(f'[ERROR]: The directory "{arg}" does not exist!')
853af6ab5fSopenharmony_ci    return os.path.abspath(arg)
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_cidef check_timeout(val):
893af6ab5fSopenharmony_ci    val = int(val)
903af6ab5fSopenharmony_ci    if val <= 0:
913af6ab5fSopenharmony_ci        raise argparse.ArgumentTypeError(f'[ERROR]: {val} is an invalid timeout value')
923af6ab5fSopenharmony_ci    return val
933af6ab5fSopenharmony_ci
943af6ab5fSopenharmony_ci
953af6ab5fSopenharmony_cidef get_args():
963af6ab5fSopenharmony_ci    description = "Generate a report on the difference between the number of v8 and es2abc bytecode instructions."
973af6ab5fSopenharmony_ci    parser = argparse.ArgumentParser(description=description)
983af6ab5fSopenharmony_ci    parser.add_argument('-v8', '-d8', '--d8_path', dest='d8_path', type=lambda arg : is_file(parser, arg),
993af6ab5fSopenharmony_ci                        help='Path to the V8 executable d8', required=True)
1003af6ab5fSopenharmony_ci    parser.add_argument('-es2abc', '--es2abc_path', dest='es2abc_path', type=lambda arg : is_file(parser, arg),
1013af6ab5fSopenharmony_ci                        help='Path to the executable program es2abc', required=True)
1023af6ab5fSopenharmony_ci    parser.add_argument('--timeout', dest='timeout', type=check_timeout, default=180,
1033af6ab5fSopenharmony_ci                        help='Time limits for use case execution (In seconds)')
1043af6ab5fSopenharmony_ci    parser.add_argument('--add_case', dest='case', type=lambda arg : is_file(parser, arg),
1053af6ab5fSopenharmony_ci                        help='Add the file path of a single test case to be executed', nargs='+')
1063af6ab5fSopenharmony_ci    parser.add_argument('--add_case_dir', dest='case_dir', type=lambda arg : is_directory(parser, arg),
1073af6ab5fSopenharmony_ci                        help='Add the directory where the test cases are to be executed', nargs='+')
1083af6ab5fSopenharmony_ci    return parser.parse_args()
1093af6ab5fSopenharmony_ci
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_cidef assemble_command(command_list: list = None, executable_program_path: str = None,
1123af6ab5fSopenharmony_ci                     file_path: str = None, parameters: list = None):
1133af6ab5fSopenharmony_ci    if command_list is None:
1143af6ab5fSopenharmony_ci        command_list = [executable_program_path, file_path]
1153af6ab5fSopenharmony_ci        if parameters:
1163af6ab5fSopenharmony_ci            command_list.extend(parameters)
1173af6ab5fSopenharmony_ci    else:
1183af6ab5fSopenharmony_ci        if executable_program_path:
1193af6ab5fSopenharmony_ci            command_list[0] = executable_program_path
1203af6ab5fSopenharmony_ci        if file_path:
1213af6ab5fSopenharmony_ci            command_list[1] = file_path
1223af6ab5fSopenharmony_ci    return command_list
1233af6ab5fSopenharmony_ci
1243af6ab5fSopenharmony_ci
1253af6ab5fSopenharmony_ciclass CaseManager:
1263af6ab5fSopenharmony_ci    def __init__(self, args, skip_test_flag=True):
1273af6ab5fSopenharmony_ci        self.test_root = os.path.dirname(os.path.abspath(__file__))
1283af6ab5fSopenharmony_ci        self.args = args
1293af6ab5fSopenharmony_ci        self.case_list = []
1303af6ab5fSopenharmony_ci        self.skip_tests_info = os.path.join(self.test_root, SKIP_TEST)
1313af6ab5fSopenharmony_ci        self.report_path = os.path.join(self.test_root, DISCREPANCY_REPORT)
1323af6ab5fSopenharmony_ci
1333af6ab5fSopenharmony_ci        self.get_test_case()
1343af6ab5fSopenharmony_ci
1353af6ab5fSopenharmony_ci        if skip_test_flag and os.path.exists(self.skip_tests_info):
1363af6ab5fSopenharmony_ci            self.skip_cases()
1373af6ab5fSopenharmony_ci
1383af6ab5fSopenharmony_ci        self.case_list.sort()
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci        # Creating dictionary: {file_path : [d8 status, es2abc status]}
1413af6ab5fSopenharmony_ci        self.crash_dict = {file_path : [SUCCESS_STATUS, SUCCESS_STATUS] for file_path in self.case_list}
1423af6ab5fSopenharmony_ci
1433af6ab5fSopenharmony_ci    def get_test_case(self):
1443af6ab5fSopenharmony_ci        def add_directory_to_case_list(case_dir, case_list, extension='js', recursive=True):
1453af6ab5fSopenharmony_ci            if not os.path.isdir(case_dir):
1463af6ab5fSopenharmony_ci                print(f'[ERROR]: add_directory_to_case_list failed! {case_dir} does not exist!')
1473af6ab5fSopenharmony_ci                return False
1483af6ab5fSopenharmony_ci            glob_expression = os.path.join(case_dir, f'**/*.{extension}')
1493af6ab5fSopenharmony_ci            files_list = glob.glob(glob_expression, recursive=recursive)
1503af6ab5fSopenharmony_ci            for file in files_list:
1513af6ab5fSopenharmony_ci                abs_file_path = os.path.abspath(file)
1523af6ab5fSopenharmony_ci                if abs_file_path not in case_list:   # make sure no duplicate case
1533af6ab5fSopenharmony_ci                    case_list.append(abs_file_path)
1543af6ab5fSopenharmony_ci            return True
1553af6ab5fSopenharmony_ci
1563af6ab5fSopenharmony_ci        if self.args.case is not None:
1573af6ab5fSopenharmony_ci            for case in self.args.case:
1583af6ab5fSopenharmony_ci                abs_file_path = os.path.abspath(case)
1593af6ab5fSopenharmony_ci                if abs_file_path not in self.case_list:
1603af6ab5fSopenharmony_ci                    self.case_list.append(abs_file_path)
1613af6ab5fSopenharmony_ci
1623af6ab5fSopenharmony_ci        if self.args.case_dir is not None:
1633af6ab5fSopenharmony_ci            for case in self.args.case_dir:
1643af6ab5fSopenharmony_ci                add_directory_to_case_list(case, self.case_list)
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ci        cur_dir = os.getcwd()
1673af6ab5fSopenharmony_ci        os.chdir(self.test_root)
1683af6ab5fSopenharmony_ci
1693af6ab5fSopenharmony_ci        # add workload cases
1703af6ab5fSopenharmony_ci        case_dir_path = self.pull_cases_from_repo(WORKLOAD_URL, 'test_cases/ark-workload')
1713af6ab5fSopenharmony_ci        if case_dir_path:
1723af6ab5fSopenharmony_ci            print('[INFO]: pull workload cases Success!')
1733af6ab5fSopenharmony_ci            case_dir_path = os.path.join(case_dir_path, 'weekly_workload', 'js')
1743af6ab5fSopenharmony_ci            add_directory_to_case_list(case_dir_path, self.case_list)
1753af6ab5fSopenharmony_ci
1763af6ab5fSopenharmony_ci        # add benchmark cases
1773af6ab5fSopenharmony_ci        sys.path.insert(0, BENCHMARK_PATH)
1783af6ab5fSopenharmony_ci        from utils import DEFAULT_TESTCASES_DIR, pull_cases, clear_folder_shutil
1793af6ab5fSopenharmony_ci        benchmark_case_path = os.path.join(BENCHMARK_PATH, DEFAULT_TESTCASES_DIR)
1803af6ab5fSopenharmony_ci        clear_folder_shutil(benchmark_case_path)
1813af6ab5fSopenharmony_ci        pull_benchmark_cases_success = pull_cases()
1823af6ab5fSopenharmony_ci        if pull_benchmark_cases_success:
1833af6ab5fSopenharmony_ci            print('[INFO]: pull benchmark cases Success!')
1843af6ab5fSopenharmony_ci            add_directory_to_case_list(benchmark_case_path, self.case_list)
1853af6ab5fSopenharmony_ci
1863af6ab5fSopenharmony_ci        os.chdir(cur_dir)
1873af6ab5fSopenharmony_ci
1883af6ab5fSopenharmony_ci    def git_clone(self, git_url, code_dir, pull=False):
1893af6ab5fSopenharmony_ci        cur_dir = os.getcwd()
1903af6ab5fSopenharmony_ci        cmd = ['git', 'clone', git_url, code_dir]
1913af6ab5fSopenharmony_ci        if pull:
1923af6ab5fSopenharmony_ci            os.chdir(code_dir)
1933af6ab5fSopenharmony_ci            cmd = ['git', 'pull']
1943af6ab5fSopenharmony_ci        process = subprocess.Popen(cmd)
1953af6ab5fSopenharmony_ci        process.wait()
1963af6ab5fSopenharmony_ci        os.chdir(cur_dir)
1973af6ab5fSopenharmony_ci        result = True
1983af6ab5fSopenharmony_ci        if process.returncode:
1993af6ab5fSopenharmony_ci            print(f"\n[ERROR]: git clone or pull '{git_url}' Failed!")
2003af6ab5fSopenharmony_ci            result = False
2013af6ab5fSopenharmony_ci        return result
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_ci    def pull_cases_from_repo(self, case_url, case_dir):
2043af6ab5fSopenharmony_ci        dir_path = os.path.join(self.test_root, case_dir)
2053af6ab5fSopenharmony_ci        pull = False
2063af6ab5fSopenharmony_ci        if os.path.exists(dir_path):
2073af6ab5fSopenharmony_ci            pull = True
2083af6ab5fSopenharmony_ci        clone_result = self.git_clone(case_url, dir_path, pull)
2093af6ab5fSopenharmony_ci        if not clone_result:
2103af6ab5fSopenharmony_ci            return None
2113af6ab5fSopenharmony_ci        return dir_path
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_ci    def skip_cases(self):
2143af6ab5fSopenharmony_ci        with open(self.skip_tests_info, 'r') as f:
2153af6ab5fSopenharmony_ci            data = json.load(f)
2163af6ab5fSopenharmony_ci
2173af6ab5fSopenharmony_ci        skip_case_list = []
2183af6ab5fSopenharmony_ci        for reason_files_dict in data:
2193af6ab5fSopenharmony_ci            skip_case_list.extend([os.path.abspath(os.path.join(self.test_root, case))
2203af6ab5fSopenharmony_ci                                   for case in reason_files_dict['files']])
2213af6ab5fSopenharmony_ci
2223af6ab5fSopenharmony_ci        self.case_list = [case for case in self.case_list if case not in skip_case_list]
2233af6ab5fSopenharmony_ci
2243af6ab5fSopenharmony_ci    def calculate_ratio_for_discrepancy_report(self, d8_instruction_number, es2abc_instruction_number):
2253af6ab5fSopenharmony_ci        if d8_instruction_number <= 0 or es2abc_instruction_number <= 0:
2263af6ab5fSopenharmony_ci            return 'Invalid Ratio'
2273af6ab5fSopenharmony_ci        ratio = (float(es2abc_instruction_number) / d8_instruction_number) * 100
2283af6ab5fSopenharmony_ci        return f'{ratio:.2f}%'
2293af6ab5fSopenharmony_ci
2303af6ab5fSopenharmony_ci    def generate_discrepancy_report(self, d8_output, es2abc_output):
2313af6ab5fSopenharmony_ci        global HTML_CONTENT
2323af6ab5fSopenharmony_ci        case_number = 1
2333af6ab5fSopenharmony_ci        for d8_item, es2abc_item in zip(d8_output, es2abc_output):
2343af6ab5fSopenharmony_ci            d8_instruction_number = d8_item[1]
2353af6ab5fSopenharmony_ci            es2abc_instruction_number = es2abc_item[1]
2363af6ab5fSopenharmony_ci
2373af6ab5fSopenharmony_ci            if self.crash_dict[d8_item[0]][0] == CRASH_STATUS:
2383af6ab5fSopenharmony_ci                d8_instruction_number = \
2393af6ab5fSopenharmony_ci                    "<span style='color:Red; font-weight:bold;'>{}</span>".format(d8_item[1])
2403af6ab5fSopenharmony_ci            elif self.crash_dict[d8_item[0]][0] == TIMEOUT_STATUS:
2413af6ab5fSopenharmony_ci                d8_instruction_number = \
2423af6ab5fSopenharmony_ci                    "<span style='color:DarkRed; font-weight:bold;'>{}</span>".format(d8_item[1])
2433af6ab5fSopenharmony_ci
2443af6ab5fSopenharmony_ci            if self.crash_dict[es2abc_item[0]][1] == CRASH_STATUS:
2453af6ab5fSopenharmony_ci                es2abc_instruction_number = \
2463af6ab5fSopenharmony_ci                    "<span style='color:Red; font-weight:bold;'>{}</span>".format(es2abc_item[1])
2473af6ab5fSopenharmony_ci            elif self.crash_dict[es2abc_item[0]][1] == TIMEOUT_STATUS:
2483af6ab5fSopenharmony_ci                es2abc_instruction_number = \
2493af6ab5fSopenharmony_ci                    "<span style='color:DarkRed; font-weight:bold;'>{}</span>".format(es2abc_item[1])
2503af6ab5fSopenharmony_ci            case_path = os.path.relpath(d8_item[0], self.test_root)
2513af6ab5fSopenharmony_ci            html_content_of_case_info = f"""<tr>
2523af6ab5fSopenharmony_ci                                    <td>{case_number}</td>
2533af6ab5fSopenharmony_ci                                    <td>{case_path}</td>
2543af6ab5fSopenharmony_ci                                    <td>{es2abc_instruction_number}</td>
2553af6ab5fSopenharmony_ci                                    <td>{d8_instruction_number}</td>
2563af6ab5fSopenharmony_ci                                    <td>{self.calculate_ratio_for_discrepancy_report(int(d8_item[1]),
2573af6ab5fSopenharmony_ci                                         int(es2abc_item[1]))}</td>
2583af6ab5fSopenharmony_ci                                </tr>"""
2593af6ab5fSopenharmony_ci            HTML_CONTENT = "{}{}".format(HTML_CONTENT, html_content_of_case_info)
2603af6ab5fSopenharmony_ci            case_number += 1
2613af6ab5fSopenharmony_ci
2623af6ab5fSopenharmony_ci        html_content_of_end_tag = "</table></body></html>"
2633af6ab5fSopenharmony_ci        HTML_CONTENT = "{}{}".format(HTML_CONTENT, html_content_of_end_tag)
2643af6ab5fSopenharmony_ci
2653af6ab5fSopenharmony_ci        flags = os.O_RDWR | os.O_CREAT
2663af6ab5fSopenharmony_ci        mode = stat.S_IWUSR | stat.S_IRUSR
2673af6ab5fSopenharmony_ci        with os.fdopen(os.open(self.report_path + '.html', flags, mode), 'w') as f:
2683af6ab5fSopenharmony_ci            f.truncate()
2693af6ab5fSopenharmony_ci            f.write(HTML_CONTENT)
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci
2723af6ab5fSopenharmony_ciclass Runner(ABC):
2733af6ab5fSopenharmony_ci    def __init__(self, command_list:list, case_manager:CaseManager):
2743af6ab5fSopenharmony_ci        self.output = []
2753af6ab5fSopenharmony_ci        self.command_list = command_list
2763af6ab5fSopenharmony_ci        self.case_manager = case_manager
2773af6ab5fSopenharmony_ci
2783af6ab5fSopenharmony_ci    @abstractmethod
2793af6ab5fSopenharmony_ci    def run(self):
2803af6ab5fSopenharmony_ci        pass
2813af6ab5fSopenharmony_ci
2823af6ab5fSopenharmony_ci
2833af6ab5fSopenharmony_ciclass D8Runner(Runner):
2843af6ab5fSopenharmony_ci    def __init__(self, command_list, case_manager):
2853af6ab5fSopenharmony_ci        super().__init__(command_list, case_manager)
2863af6ab5fSopenharmony_ci
2873af6ab5fSopenharmony_ci    def run(self):
2883af6ab5fSopenharmony_ci        for file_path in self.case_manager.case_list:
2893af6ab5fSopenharmony_ci            d8_case_path = file_path.replace('.js', '.mjs')
2903af6ab5fSopenharmony_ci            shutil.copyfile(file_path, d8_case_path)
2913af6ab5fSopenharmony_ci            instruction_number = RecognizeInstructionMethod.recognize_d8_bytecode_instruction(
2923af6ab5fSopenharmony_ci                self.command_list, d8_case_path, self.case_manager)
2933af6ab5fSopenharmony_ci            if os.path.exists(d8_case_path):
2943af6ab5fSopenharmony_ci                os.remove(d8_case_path)
2953af6ab5fSopenharmony_ci            self.output.append((file_path, instruction_number))
2963af6ab5fSopenharmony_ci
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ciclass ES2ABCRunner(Runner):
2993af6ab5fSopenharmony_ci    def __init__(self, command_list, case_manager):
3003af6ab5fSopenharmony_ci        super().__init__(command_list, case_manager)
3013af6ab5fSopenharmony_ci
3023af6ab5fSopenharmony_ci    def run(self):
3033af6ab5fSopenharmony_ci        for file_path in self.case_manager.case_list:
3043af6ab5fSopenharmony_ci            instruction_number = RecognizeInstructionMethod.recognize_es2abc_bytecode_instruction(
3053af6ab5fSopenharmony_ci                self.command_list, file_path, self.case_manager)
3063af6ab5fSopenharmony_ci            self.output.append((file_path, instruction_number))
3073af6ab5fSopenharmony_ci
3083af6ab5fSopenharmony_ci
3093af6ab5fSopenharmony_ciclass RecognizeInstructionMethod:
3103af6ab5fSopenharmony_ci    @staticmethod
3113af6ab5fSopenharmony_ci    def recognize_d8_bytecode_instruction(command_list, file_path, case_manager):
3123af6ab5fSopenharmony_ci        original_file_path = file_path.replace('.mjs', '.js')
3133af6ab5fSopenharmony_ci        command_list = assemble_command(command_list, file_path=file_path)
3143af6ab5fSopenharmony_ci        process = subprocess.Popen(command_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
3153af6ab5fSopenharmony_ci        try:
3163af6ab5fSopenharmony_ci            output, _ = process.communicate(timeout=case_manager.args.timeout)
3173af6ab5fSopenharmony_ci        except subprocess.TimeoutExpired:
3183af6ab5fSopenharmony_ci            print(f"[WARNING]: v8 - Killed! Timeout: {file_path}")
3193af6ab5fSopenharmony_ci            process.kill()
3203af6ab5fSopenharmony_ci            case_manager.crash_dict[original_file_path][0] = TIMEOUT_STATUS
3213af6ab5fSopenharmony_ci            return -1   # Script execution timeout sets the instruction number to -1
3223af6ab5fSopenharmony_ci        process.wait()
3233af6ab5fSopenharmony_ci
3243af6ab5fSopenharmony_ci        if process.returncode != 0:
3253af6ab5fSopenharmony_ci            case_manager.crash_dict[original_file_path][0] = CRASH_STATUS
3263af6ab5fSopenharmony_ci            print(f'[WARNING]: v8 - Crashed! {file_path}')
3273af6ab5fSopenharmony_ci
3283af6ab5fSopenharmony_ci        decoded_output = output.decode('utf-8', errors='ignore')
3293af6ab5fSopenharmony_ci
3303af6ab5fSopenharmony_ci        instruction_pattern = r'0x[0-9a-fA-F]+ @\s+\d+\s+:\s+([0-9a-fA-F\s]+)\s+(.*)$'
3313af6ab5fSopenharmony_ci        result = re.finditer(instruction_pattern, decoded_output, re.MULTILINE)
3323af6ab5fSopenharmony_ci        instruction_number = sum(1 for _ in result)
3333af6ab5fSopenharmony_ci        return instruction_number
3343af6ab5fSopenharmony_ci
3353af6ab5fSopenharmony_ci    @staticmethod
3363af6ab5fSopenharmony_ci    def recognize_es2abc_bytecode_instruction(command_list, file_path, case_manager):
3373af6ab5fSopenharmony_ci        command_list = assemble_command(command_list, file_path=file_path)
3383af6ab5fSopenharmony_ci        process = subprocess.Popen(command_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
3393af6ab5fSopenharmony_ci        try:
3403af6ab5fSopenharmony_ci            output, _ = process.communicate(timeout=case_manager.args.timeout)
3413af6ab5fSopenharmony_ci        except subprocess.TimeoutExpired:
3423af6ab5fSopenharmony_ci            print(f"[WARNING]: es2abc - Killed! Timeout: {file_path}")
3433af6ab5fSopenharmony_ci            process.kill()
3443af6ab5fSopenharmony_ci            case_manager.crash_dict[file_path][1] = TIMEOUT_STATUS
3453af6ab5fSopenharmony_ci            return -1    # Script execution timeout sets the instructions number to -1
3463af6ab5fSopenharmony_ci        process.wait()
3473af6ab5fSopenharmony_ci
3483af6ab5fSopenharmony_ci        if process.returncode != 0:
3493af6ab5fSopenharmony_ci            case_manager.crash_dict[file_path][1] = CRASH_STATUS
3503af6ab5fSopenharmony_ci            print(f'[WARNING]: es2abc - Crashed! {file_path}')
3513af6ab5fSopenharmony_ci
3523af6ab5fSopenharmony_ci        decoded_output = output.decode('utf-8', errors='ignore')
3533af6ab5fSopenharmony_ci        lines = decoded_output.split('\n')
3543af6ab5fSopenharmony_ci        instruction_number = 0
3553af6ab5fSopenharmony_ci        for line in lines:
3563af6ab5fSopenharmony_ci            if 'instructions_number:' in line:
3573af6ab5fSopenharmony_ci                instruction_number = line.split('instructions_number:')[-1].strip()
3583af6ab5fSopenharmony_ci                break
3593af6ab5fSopenharmony_ci        return instruction_number
3603af6ab5fSopenharmony_ci
3613af6ab5fSopenharmony_ci
3623af6ab5fSopenharmony_cidef main():
3633af6ab5fSopenharmony_ci    args = get_args()
3643af6ab5fSopenharmony_ci
3653af6ab5fSopenharmony_ci    d8_command = assemble_command(executable_program_path=args.d8_path, parameters=['--print-bytecode'])
3663af6ab5fSopenharmony_ci    es2abc_command = assemble_command(executable_program_path=args.es2abc_path,
3673af6ab5fSopenharmony_ci                                      parameters=['--module', '--dump-size-stat', '--output=/dev/null'])
3683af6ab5fSopenharmony_ci
3693af6ab5fSopenharmony_ci    case_manager = CaseManager(args)
3703af6ab5fSopenharmony_ci    d8_runner = D8Runner(d8_command, case_manager)
3713af6ab5fSopenharmony_ci    es2abc_runner = ES2ABCRunner(es2abc_command, case_manager)
3723af6ab5fSopenharmony_ci
3733af6ab5fSopenharmony_ci    if len(case_manager.case_list):
3743af6ab5fSopenharmony_ci        thread_d8 = threading.Thread(target=d8_runner.run)
3753af6ab5fSopenharmony_ci        thread_es2abc = threading.Thread(target=es2abc_runner.run)
3763af6ab5fSopenharmony_ci        thread_d8.start()
3773af6ab5fSopenharmony_ci        thread_es2abc.start()
3783af6ab5fSopenharmony_ci        thread_d8.join()
3793af6ab5fSopenharmony_ci        thread_es2abc.join()
3803af6ab5fSopenharmony_ci
3813af6ab5fSopenharmony_ci    case_manager.generate_discrepancy_report(d8_runner.output, es2abc_runner.output)
3823af6ab5fSopenharmony_ci
3833af6ab5fSopenharmony_ci
3843af6ab5fSopenharmony_ciif __name__ == "__main__":
3853af6ab5fSopenharmony_ci    main()