From 1406f7721f5f76740b0ca0ffd68263fef97532f8 Mon Sep 17 00:00:00 2001 From: yangxiaoshuai2022 Date: Mon, 18 Mar 2024 09:35:07 +0800 Subject: [PATCH 001/202] =?UTF-8?q?=E5=BE=AE=E4=BB=BB=E5=8A=A1=E9=98=9F?= =?UTF-8?q?=E5=88=97=E6=89=93=E7=82=B9=EF=BC=8C=E5=8C=85=E5=90=AB=E5=85=A5?= =?UTF-8?q?=E9=98=9F=E5=87=BA=E9=98=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangxiaoshuai2022 --- ecmascript/jobs/micro_job_queue.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ecmascript/jobs/micro_job_queue.cpp b/ecmascript/jobs/micro_job_queue.cpp index 851c6fc7d..1c3e4a5be 100644 --- a/ecmascript/jobs/micro_job_queue.cpp +++ b/ecmascript/jobs/micro_job_queue.cpp @@ -42,6 +42,7 @@ void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle jobQueu // 3. Assert: arguments is a List that has the same number of elements as the number of parameters required by job. // 4. Let callerContext be the running execution context. // 5. Let callerRealm be callerContext’s Realm. + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "MicroJobQueue::EnqueueJob"); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSHandle pendingJob(factory->NewPendingJob(job, argv)); @@ -60,6 +61,7 @@ void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle jobQueu void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle jobQueue) { + ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "MicroJobQueue::ExecutePendingJob"); [[maybe_unused]] EcmaHandleScope handleScope(thread); JSMutableHandle promiseQueue(thread, jobQueue->GetPromiseJobQueue()); JSMutableHandle pendingJob(thread, JSTaggedValue::Undefined()); -- Gitee From 312c64592ce82ed175ae16a80a45ddcfab113e8c Mon Sep 17 00:00:00 2001 From: Petrov Igor Date: Fri, 15 Mar 2024 10:12:37 +0800 Subject: [PATCH 002/202] [Scripts] Refactor js-perf-test launcher Issue: #I98PVS Testing: `bash run_js_perf_test.sh` Signed-off-by: Petrov Igor --- test/jsperftest/run_js_perf_test.sh | 190 +++++++++++++++++++++++----- 1 file changed, 155 insertions(+), 35 deletions(-) diff --git a/test/jsperftest/run_js_perf_test.sh b/test/jsperftest/run_js_perf_test.sh index 97ebb6e03..2ec8b3357 100755 --- a/test/jsperftest/run_js_perf_test.sh +++ b/test/jsperftest/run_js_perf_test.sh @@ -15,11 +15,91 @@ set -e declare -i ret_error=1 +declare SCRIPT_NAME +SCRIPT_NAME="$(basename "$0")" +declare JS_PERF_RESULT_PATH="" +declare OPENHARMONY_ROOT_PATH="" +declare D8_BINARY_PATH="/usr/bin/v8/d8" +declare VER_PLATFORM="full_x86_64" +declare -a BENCH_FILTER=() +declare NO_NEED_DOWNLOAD_BENCHS=false +declare BENCH_MULTIPLIER="" +declare -i ITERATIONS=1 function init() { - CUR_PATH=$(dirname "$(readlink -f "$0")") - TMP_PATH=$CUR_PATH/tmp + while [[ -n "$1" ]] + do + case $1 in + --help|-h) + usage + exit 0 + ;; + --d8-path) + shift + D8_BINARY_PATH="$1" + ;; + --platform) + shift + VER_PLATFORM="$1" + ;; + --bench-filter=*) + local BENCH_FILTER_STR="${1#*=}" + BENCH_FILTER=(${BENCH_FILTER_STR//:/ }) + ;; + --no-download-benchs) + NO_NEED_DOWNLOAD_BENCHS=true + ;; + --multiplier) + shift + BENCH_MULTIPLIER=$1 + ;; + --iterations) + shift + ITERATIONS=$1 + ;; + *) + JS_PERF_RESULT_PATH="$(realpath "$1")" + OPENHARMONY_ROOT_PATH="$2" + break + ;; + esac + shift + done + if [[ -z "${OPENHARMONY_ROOT_PATH}" || -z "${JS_PERF_RESULT_PATH}" ]] + then + usage + echo "Invalid input arguments" + exit 1 + fi + if [[ ! -d "${OPENHARMONY_ROOT_PATH}" ]] + then + echo "Path to openharmony root dir does not exist: ${OPENHARMONY_ROOT_PATH}" + exit 1 + else + OPENHARMONY_ROOT_PATH="$(realpath "${OPENHARMONY_ROOT_PATH}")" + fi + if [[ ! -x "${D8_BINARY_PATH}" ]] + then + echo "Executable file does not exist: ${D8_BINARY_PATH}" + exit 1 + fi + if [[ ! -d "${JS_PERF_RESULT_PATH}" ]] + then + mkdir -p "${JS_PERF_RESULT_PATH}" + fi + WORKDIR_PATH="${JS_PERF_RESULT_PATH}/workdir" + if [[ -d "${WORKDIR_PATH}" ]] + then + rm -rf "${WORKDIR_PATH}" + fi + mkdir -p "${WORKDIR_PATH}" + echo " +OpenHarmony root path: ${OPENHARMONY_ROOT_PATH} +D8 path: ${D8_BINARY_PATH} +JS perf results: ${JS_PERF_RESULT_PATH} +Platform: ${VER_PLATFORM} +" } function check_command_exist() @@ -35,39 +115,71 @@ function check_pip_component() return $? } -function download_js_test_files() +function prepare_js_test_files() { - code_path="$TMP_PATH"/code/arkjs-perf-test - if [ -d "$code_path" ];then - JS_TEST_PATH=$code_path/js-perf-test - return + local -r bench_repo_path="${JS_PERF_RESULT_PATH}/code/arkjs-perf-test" + if ! ${NO_NEED_DOWNLOAD_BENCHS} + then + rm -rf "${bench_repo_path}" + fi + if [[ ! -d "${bench_repo_path}" ]] + then + mkdir -p "${bench_repo_path}" + git clone -b builtins_test1110 https://gitee.com/dov1s/arkjs-perf-test.git "${bench_repo_path}" + fi + local -r test_dir="js-perf-test" + JS_TEST_PATH="${JS_PERF_RESULT_PATH}/${test_dir}" + if [[ -d "${JS_TEST_PATH}" ]] + then + rm -rf "${JS_TEST_PATH}" + fi + mkdir -p "${JS_TEST_PATH}" + if [[ ${#BENCH_FILTER[@]} -eq 0 ]] + then + cp -r "${bench_repo_path}/${test_dir}"/* "${JS_TEST_PATH}" + else + for bench in "${BENCH_FILTER[@]}" + do + if [[ -d "${bench_repo_path}/${test_dir}/${bench}" ]] + then + mkdir -p "${JS_TEST_PATH}/${bench}" + cp -r "${bench_repo_path}/${test_dir}/${bench}"/* "${JS_TEST_PATH}/${bench}" + elif [[ -f "${bench_repo_path}/${test_dir}/${bench}" ]] + then + mkdir -p "$(dirname "${JS_TEST_PATH}/${bench}")" + cp "${bench_repo_path}/${test_dir}/${bench}" "${JS_TEST_PATH}/${bench}" + else + echo "No benchmarks for filter '${bench}'" + fi + done fi +} + +function usage() +{ + echo "${SCRIPT_NAME} [options] +Options: + --d8-path - path to d8 binary file. + Default: /usr/bin/v8/d8 + --platform - used platform. Possible values in config.json. + Default: full_x86_64 + --multiplier N - iteration multiplier for js benchmarks + --iterations N - number of benchmark launches and get average + --bench-filter=BenchDir1:BenchDir2:BenchDir3/bench.js:... + - filter for benchmarks: directory or file + --no-download-benchs - no download benchmarks from repository if repo already exists + --help, -h - print help info about script - mkdir -p "$code_path" - echo "$code_path" - git clone -b builtins_test1110 https://gitee.com/dov1s/arkjs-perf-test.git "$code_path" - JS_TEST_PATH=$code_path/js-perf-test +Positional arguments: + JS_PERF_RESULT_PATH - directory path to benchmark results + OPENHARMONY_ROOT - path to root directory for ark_js_vm and es2panda +" } main() { - init - js_perf_test_archive_path=$1 - OPENHARMONY_OUT_PATH=$2 - D8_BINARY_PATH=$3 - if [ $# -ge 4 ]; then - iterations_multiplier=$4 - fi - - VER_PLATFORM="full_x86_64" - if [ $# == 5 ]; then - VER_PLATFORM=$5 - fi + init "$@" cur_path=$(dirname "$(readlink -f "$0")") - - if [ ! -d "$js_perf_test_archive_path" ];then - mkdir -p "js_perf_test_archive_path" - fi check_command_exist git || { echo "git is not available"; return $ret_error; } check_command_exist unzip || { echo "unzip is not available"; return $ret_error; } @@ -77,17 +189,25 @@ main() [ -f "$cur_path/run_js_test.py" ] || { echo "no run_js_test.py, please check it";return $ret_error;} - download_js_test_files || { return $ret_error; } + prepare_js_test_files || { return $ret_error; } - if [ ! -z $iterations_multiplier ]; then - for js_test in `find $JS_TEST_PATH -name "*js"`; do - python3 $cur_path/prerun_proc.py __MULTIPLIER__=$iterations_multiplier $js_test + cd "${WORKDIR_PATH}" + if [[ -n ${BENCH_MULTIPLIER} ]] + then + for js_test in $(find ${JS_TEST_PATH} -name "*js") + do + python3 ${cur_path}/prerun_proc.py __MULTIPLIER__=${BENCH_MULTIPLIER} "${js_test}" done fi - - echo "LD_LIBRARY_PATH:$LD_LIBRARY_PATH" - python3 "$cur_path"/run_js_test.py -bp "$OPENHARMONY_OUT_PATH" -p "$JS_TEST_PATH" -o "$js_perf_test_archive_path"\ - -v "$D8_BINARY_PATH" -e "$VER_PLATFORM" + mkdir -p "${WORKDIR_PATH}/tmp" + echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" + python3 "${cur_path}"/run_js_test.py \ + -bp "${OPENHARMONY_ROOT_PATH}" \ + -p "${JS_TEST_PATH}" \ + -o "${JS_PERF_RESULT_PATH}" \ + -v "${D8_BINARY_PATH}" \ + -e "${VER_PLATFORM}" \ + -n "${ITERATIONS}" } main "$@" -- Gitee From 341d5b773ec790c06c83ea87f51b5a00e93dfd43 Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Wed, 13 Mar 2024 17:20:49 +0800 Subject: [PATCH 003/202] Imporve js perf bench script Issue: #I98PVS Testing: `bash run_js_perf_test.sh [options]` Co-authored-by: Petrov Igor Co-authored-by: Artem Udovichenko Signed-off-by: Petrov Igor --- test/jsperftest/run_js_perf_test.sh | 12 +- test/jsperftest/run_js_test.py | 199 +++++++++++++++------------- 2 files changed, 116 insertions(+), 95 deletions(-) diff --git a/test/jsperftest/run_js_perf_test.sh b/test/jsperftest/run_js_perf_test.sh index 2ec8b3357..7aa92d31f 100755 --- a/test/jsperftest/run_js_perf_test.sh +++ b/test/jsperftest/run_js_perf_test.sh @@ -59,7 +59,7 @@ function init() ITERATIONS=$1 ;; *) - JS_PERF_RESULT_PATH="$(realpath "$1")" + JS_PERF_RESULT_PATH="$1" OPENHARMONY_ROOT_PATH="$2" break ;; @@ -88,6 +88,7 @@ function init() then mkdir -p "${JS_PERF_RESULT_PATH}" fi + JS_PERF_RESULT_PATH="$(realpath "${JS_PERF_RESULT_PATH}")" WORKDIR_PATH="${JS_PERF_RESULT_PATH}/workdir" if [[ -d "${WORKDIR_PATH}" ]] then @@ -192,15 +193,17 @@ main() prepare_js_test_files || { return $ret_error; } cd "${WORKDIR_PATH}" - if [[ -n ${BENCH_MULTIPLIER} ]] + if [[ -n "${BENCH_MULTIPLIER}" ]] then for js_test in $(find ${JS_TEST_PATH} -name "*js") do - python3 ${cur_path}/prerun_proc.py __MULTIPLIER__=${BENCH_MULTIPLIER} "${js_test}" + python3 "${cur_path}"/prerun_proc.py __MULTIPLIER__="${BENCH_MULTIPLIER}" "${js_test}" done fi mkdir -p "${WORKDIR_PATH}/tmp" echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" + local -i benchs_time_start benchs_time benchs_minutes + benchs_time_start=$(date +%s) python3 "${cur_path}"/run_js_test.py \ -bp "${OPENHARMONY_ROOT_PATH}" \ -p "${JS_TEST_PATH}" \ @@ -208,6 +211,9 @@ main() -v "${D8_BINARY_PATH}" \ -e "${VER_PLATFORM}" \ -n "${ITERATIONS}" + benchs_time=$(($(date +%s) - benchs_time_start)) + benchs_minutes=$((benchs_time / 60)) + echo "Benchmark script time: ${benchs_minutes} min $((benchs_time - benchs_minutes * 60)) sec" } main "$@" diff --git a/test/jsperftest/run_js_test.py b/test/jsperftest/run_js_test.py index b9ce828dc..f9a63bbb9 100644 --- a/test/jsperftest/run_js_test.py +++ b/test/jsperftest/run_js_test.py @@ -25,6 +25,7 @@ import os import shutil import stat import subprocess +from typing import Union from collections import namedtuple from openpyxl import Workbook, load_workbook from openpyxl.styles import PatternFill @@ -152,6 +153,15 @@ def ark_divide_v_8_compute(exec_time, v_8_excute_time): return ark_divide_v_8 +def cast_to_float_or_str(value: str) -> Union[float, str]: + """Return float value by str if it is possible, return input str otherwise""" + try: + result = float(value) + except ValueError: + result = value + return result + + def append_row_data(report_file, case_test_data): wb = load_workbook(report_file) ws = wb.worksheets[0] @@ -187,9 +197,14 @@ def append_row_data(report_file, case_test_data): ark_divide_v_8_with_jitless = str("{:.2f}".format(float(exec_time) / float(v_8_jitless_excute_time))) jis_case_file_name_with_class = Constants.JS_FILE_SUPER_LINK_DICT['/'.join([class_name, api_name])] js_file_super_link = '/'.join([Constants.HYPERLINK_HEAD, jis_case_file_name_with_class]) - new_row = [js_case_name, scene, excute_status, exec_time, yesterday_excute_time, - is_degraded_str, v_8_excute_time, v_8_jitless_excute_time, ark_divide_v_8, - ark_divide_v_8_with_jitless, js_file_super_link, ' '] + new_row = [js_case_name, scene, excute_status, + cast_to_float_or_str(exec_time), yesterday_excute_time, + is_degraded_str, + cast_to_float_or_str(v_8_excute_time), + cast_to_float_or_str(v_8_jitless_excute_time), + cast_to_float_or_str(ark_divide_v_8), + cast_to_float_or_str(ark_divide_v_8_with_jitless), + js_file_super_link, ' '] ws.append(new_row) if is_degraded_str is str(True): ws.cell(row=ws.max_row, column=6).fill = PatternFill(start_color='FF0000', end_color='FF0000', @@ -207,8 +222,7 @@ def append_row_data(report_file, case_test_data): wb.save(report_file) return Constants.RET_OK - -def run_js_case_via_ark(binary_path, js_file_path, class_name, api_name, report_file): +def run_js_case_via_ark(binary_path, js_file_path, class_name, api_name, iterations, report_file): composite_scenes = get_js_file_class_api_scenes(js_file_path) case_test_data = {} execute_status = Constants.FAIL @@ -224,16 +238,12 @@ def run_js_case_via_ark(binary_path, js_file_path, class_name, api_name, report_ os.makedirs(fangzhou_test_path) class_folder_path = os.path.join(fangzhou_test_path, class_name) - api_path = os.path.join(class_folder_path, api_name) if not os.path.exists(class_folder_path): os.makedirs(class_folder_path) - abc_file_path = api_path + ".abc" cur_abc_file = os.path.join(Constants.CUR_PATH, api_name + ".abc") api_log_path = os.path.join(class_folder_path, api_name + ".log") - es2abc_path = Constants.ES2ABC_PATH - # tranmit abc - cmd = [es2abc_path, js_file_path] + cmd = [Constants.ES2ABC_PATH, "--output", cur_abc_file, js_file_path] logger.info("run cmd: %s", cmd) ret = subprocess.run(cmd) @@ -241,14 +251,6 @@ def run_js_case_via_ark(binary_path, js_file_path, class_name, api_name, report_ logger.error("ret = %s, %s generate abc file failed. cmd: %s", str(ret), js_file_name, cmd) append_row_data(report_file, case_test_data) return case_test_data - - cmd2 = ["cp", cur_abc_file, abc_file_path] - ret = subprocess.run(cmd2) - if ret.returncode != 0: - logger.error("ret.returncode = %s, %s generate abc file failed. cmd: %s", str(ret.returncode), js_file_name, - cmd2) - append_row_data(report_file, case_test_data) - return case_test_data # execute abc ark_js_vm_path = Constants.ARK_JS_VM_PATH cmd = [ark_js_vm_path, "--log-level=info", "--enable-runtime-stat=true", "--icu-data-path", @@ -257,38 +259,33 @@ def run_js_case_via_ark(binary_path, js_file_path, class_name, api_name, report_ logger.info("run cmd: %s", cmd) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL modes = stat.S_IWUSR | stat.S_IRUSR - if os.path.exists(api_log_path): - os.remove(api_log_path) - with os.fdopen(os.open(api_log_path, flags, modes), 'wb') as outfile: - ret = subprocess.run(cmd, stdout=outfile) - if ret.returncode != 0: - logger.error("%s execute abc file failed. cmd: %s", js_file_name, cmd) - append_row_data(report_file, case_test_data) - return case_test_data - else: - case_test_data.clear() + data = {} + for _ in range(iterations): if os.path.exists(api_log_path): - with open(api_log_path, 'r') as f: - for line in f: - if "scene_output" not in line: - continue - - mid_str = line.split(':')[1].strip() - scene = mid_str.split()[2] - main_key = '/'.join([js_file_name, scene]).lower() - execute_time = line.split(':')[2] - execute_status = Constants.PASS - case_test_data[main_key] = Constants.CaseTestDataType(execute_status, execute_time) - - append_row_data(report_file, case_test_data) - logger.info("%s execute abc file successfully. cmd: %s case_test_data: %s", js_file_name, cmd, case_test_data) + os.remove(api_log_path) + with os.fdopen(os.open(api_log_path, flags, modes), 'wb') as outfile: + ret = subprocess.run(cmd, stdout=outfile) + if ret.returncode != 0: + logger.error("%s execute abc file failed. cmd: %s", js_file_name, cmd) + append_row_data(report_file, case_test_data) + return case_test_data + if os.path.exists(api_log_path): + data = update_data_by_log(data, api_log_path, js_file_name[:-3]) + + case_test_data.clear() + execute_status = Constants.PASS + for k, time_value in data.items(): + case_test_data[k] = Constants.CaseTestDataType(execute_status, str(time_value / iterations)) + append_row_data(report_file, case_test_data) + logger.info("%s execute abc file successfully. cmd: %s case_test_data: %s", + js_file_name, cmd, case_test_data) os.remove(cur_abc_file) return case_test_data -def run_via_ark(jspath, report_file): +def run_via_ark(jspath, report_file, iterations): if not os.path.exists(jspath): logger.error("js perf cases path is not exist. jspath: %s", jspath) logger.info("begin to run js perf test via ark. js perf cases path: %s", jspath) @@ -305,7 +302,7 @@ def run_via_ark(jspath, report_file): api_name = results[-1].split(".")[0] js_case_name = '/'.join([class_name, results[-1]]) logger.info("begin to execute %s.", js_case_name) - test_data = run_js_case_via_ark(BINARY_PATH, file_path, class_name, api_name, report_file) + test_data = run_js_case_via_ark(BINARY_PATH, file_path, class_name, api_name, iterations, report_file) for _, key in enumerate(test_data.keys()): Constants.TODAY_EXCUTE_INFO[key] = test_data.get(key) logger.info("finish executing %s. executing info: %s.", js_case_name, Constants.TODAY_EXCUTE_INFO) @@ -428,6 +425,25 @@ def append_summary_info(report_file, total_cost_time): return Constants.RET_OK +def process_args(args: argparse.Namespace) -> argparse.Namespace: + """Process and check argument values""" + if not os.path.exists(args.binarypath): + logger.error("parameter --binarypath is not exist. Please check it! binary path: %s", args.binarypath) + raise RuntimeError("error bad parameters --binarypath") + if args.output_folder_path is None: + args.output_folder_path = os.getcwd() + if not os.path.isabs(args.output_folder_path): + args.output_folder_path = os.path.abspath(args.output_folder_path) + if not os.path.exists(args.d_8_binary_path): + logger.error("parameter --d_8_binary_path is not exist. Please check it! d 8 binary path: %s", + args.d_8_binary_path) + raise RuntimeError("error bad parameters --d_8_binary_path: {}".format(args.d_8_binary_path)) + if args.iterations <= 0: + logger.error("parameter --iterations <= 0. Please check it! iterations: %s", + args.iterations) + raise RuntimeError(f"error bad parameters --iterations: {args.iterations}") + return args + def get_args(): parser = argparse.ArgumentParser() parser.add_argument( @@ -466,24 +482,14 @@ def get_args(): default="full_x86_64", help="Code repository version and platform", ) - args = parser.parse_args() - - if not os.path.exists(args.binarypath): - logger.error("parameter --binarypath is not exist. Please check it! binary path: %s", args.binarypath) - raise RuntimeError("error bad parameters --binarypath") - - if args.output_folder_path is None: - args.output_folder_path = os.getcwd() - - if not os.path.isabs(args.output_folder_path): - args.output_folder_path = os.path.abspath(args.output_folder_path) - - if not os.path.exists(args.d_8_binary_path): - logger.error("parameter --d_8_binary_path is not exist. Please check it! d 8 binary path: %s", - args.d_8_binary_path) - raise RuntimeError("error bad parameters --d_8_binary_path: {}".format(args.d_8_binary_path)) - - return args + parser.add_argument( + "--iterations", + "-n", + default=1, + type=int, + help="Number of benchmark launches" + ) + return process_args(parser.parse_args()) def init_report(report_file): @@ -572,45 +578,54 @@ def get_yesterday_excute_times(yesterday_report): excute_time = ws.cell(row=row_num, column=4).value Constants.YESTERDAY_EXCUTE_TIME_DICT[main_key] = excute_time +def update_data_by_log(data: dict, log_path: str, js_name: str) -> dict: + """Update execution time data by log file""" + with open(log_path, 'r') as f: + for line in f: + if "scene_output" not in line: + continue + str_array = line.split(':') + mid_str = str_array[1].strip() + scene = mid_str.split()[2] + exec_time = str_array[2] + key_str = '/'.join([js_name + '.js', scene]).lower() + if key_str not in data: + data[key_str] = float(exec_time) + else: + data[key_str] += float(exec_time) + return data -def run_v_8_single_js_case(js_file_path, cmd_para, js_case_name): +def run_v_8_single_js_case(js_file_path, cmd_para, js_case_name, iterations: int): v_8_exec_time_dict = {} scenes = get_js_file_class_api_scenes(js_file_path) v_8_log_path = os.path.join(Constants.CUR_PATH, "v_8.log") - if os.path.exists(v_8_log_path): - os.remove(v_8_log_path) flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL modes = stat.S_IWUSR | stat.S_IRUSR - with os.fdopen(os.open(v_8_log_path, flags, modes), 'wb') as outfile: - if len(cmd_para) == 0: - cmd = [Constants.V_8_ENGINED_PATH, js_file_path] - else: - cmd = [Constants.V_8_ENGINED_PATH, cmd_para, js_file_path] - logger.info("run cmd:%s", cmd) - ret = subprocess.run(cmd, stdout=outfile) + if len(cmd_para) == 0: + cmd = [Constants.V_8_ENGINED_PATH, js_file_path] + else: + cmd = [Constants.V_8_ENGINED_PATH, cmd_para, js_file_path] + logger.info("run cmd:%s", cmd) + data = {} + for _ in range(iterations): + if os.path.exists(v_8_log_path): + os.remove(v_8_log_path) + with os.fdopen(os.open(v_8_log_path, flags, modes), 'wb') as outfile: + ret = subprocess.run(cmd, stdout=outfile, check=False) if ret.returncode != 0: for elem in enumerate(scenes): v_8_exec_time_dict[elem] = 0 logger.error("execute cmd failed. cmd: %s", cmd) return v_8_exec_time_dict + data = update_data_by_log(data, v_8_log_path, js_case_name) + os.remove(v_8_log_path) + for k, time_value in data.items(): + v_8_exec_time_dict[k] = str(time_value / iterations) logger.info("v 8 excute %s successfully. cmd: %s", js_file_path, cmd) - - with open(v_8_log_path, 'r') as f: - for line in f: - if "scene_output" not in line: - continue - str_array = line.split(':') - mid_str = str_array[1].strip() - scene = mid_str.split()[2] - exec_time = str_array[2] - key_str = '/'.join([js_case_name + '.js', scene]).lower() - v_8_exec_time_dict[key_str] = exec_time - - os.remove(v_8_log_path) return v_8_exec_time_dict @@ -632,7 +647,7 @@ def get_given_column_data(report_file, column_index): return column_data -def get_v_8_excute_times(jspath, v_8_based_report_file): +def get_v_8_excute_times(jspath, v_8_based_report_file, iterations): if os.path.exists(v_8_based_report_file) and os.path.isfile(v_8_based_report_file): # Generate v 8 benchmark data on the 1st, 11th, and 21st of each month.The testing at other times refers to # these V 8 benchmark data @@ -654,14 +669,14 @@ def get_v_8_excute_times(jspath, v_8_based_report_file): api_name = results[-1].split(".")[0] js_case_name = '/'.join([class_name, api_name]) - v_8_exec_time_dict = run_v_8_single_js_case(file_path, '', js_case_name) + v_8_exec_time_dict = run_v_8_single_js_case(file_path, '', js_case_name, iterations) for key in v_8_exec_time_dict.keys(): Constants.V_8_EXCUTE_TIME_DICT[key] = v_8_exec_time_dict[key] return Constants.RET_OK -def get_v_8_jitless_excute_times(jspath, v_8_based_report_file_path): +def get_v_8_jitless_excute_times(jspath, v_8_based_report_file_path, iterations): if os.path.exists(v_8_based_report_file_path) and os.path.isfile(v_8_based_report_file_path): # Generate v 8 benchmark data on the 1st, 11th, and 21st of each month.The testing at other times refers to # these V 8 benchmark data @@ -684,7 +699,7 @@ def get_v_8_jitless_excute_times(jspath, v_8_based_report_file_path): api_name = results[-1].split(".")[0] js_case_name = '/'.join([class_name, api_name]) - v_8_exec_time_dict = run_v_8_single_js_case(file_path, '--jitless', js_case_name) + v_8_exec_time_dict = run_v_8_single_js_case(file_path, '--jitless', js_case_name, iterations) for key in v_8_exec_time_dict.keys(): Constants.V_8_JITLESS_EXCUTE_TIME_DICT[key] = v_8_exec_time_dict[key] @@ -749,10 +764,10 @@ if __name__ == "__main__": init_report(TODAY_EXCEL_PATH) get_yesterday_excute_times(YESTERDAY_EXCEL_PATH) v_8_based_report_path = get_v_8_benchmark_daily_report_path() - get_v_8_excute_times(paras.jspath, v_8_based_report_path) - get_v_8_jitless_excute_times(paras.jspath, v_8_based_report_path) + get_v_8_excute_times(paras.jspath, v_8_based_report_path, paras.iterations) + get_v_8_jitless_excute_times(paras.jspath, v_8_based_report_path, paras.iterations) - run_via_ark(paras.jspath, TODAY_EXCEL_PATH) + run_via_ark(paras.jspath, TODAY_EXCEL_PATH, paras.iterations) end_time = datetime.datetime.now(tz=datetime.timezone.utc) totol_time = u"%s" % (end_time - start_time) -- Gitee From ba7352ae82907f36b19bc218273626acb93ad336 Mon Sep 17 00:00:00 2001 From: chenlincl3 <932565568@qq.com> Date: Thu, 14 Mar 2024 11:27:55 +0800 Subject: [PATCH 004/202] =?UTF-8?q?=E6=94=AF=E6=92=91=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E8=B7=B3=E8=BD=AC=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: chenlincl3 Change-Id: I7b56facf8d5470fab866bea58856c977234e0de3 --- .../jspandafile/js_pandafile_executor.cpp | 42 +++++++++++++++++++ .../jspandafile/js_pandafile_executor.h | 3 ++ ecmascript/module/module_path_helper.h | 2 +- ecmascript/napi/include/jsnapi_expo.h | 2 + ecmascript/napi/jsnapi_expo.cpp | 17 ++++++++ 5 files changed, 65 insertions(+), 1 deletion(-) diff --git a/ecmascript/jspandafile/js_pandafile_executor.cpp b/ecmascript/jspandafile/js_pandafile_executor.cpp index 807a8d129..e264aca95 100644 --- a/ecmascript/jspandafile/js_pandafile_executor.cpp +++ b/ecmascript/jspandafile/js_pandafile_executor.cpp @@ -350,4 +350,46 @@ Expected JSPandaFileExecutor::ExecuteModuleBufferSecure(JST } return CommonExecuteBuffer(thread, name, entry, jsPandaFile.get()); } + +Expected JSPandaFileExecutor::ExecuteAbcFileWithFlag(JSThread *thread, const CString &bundleName, + const CString &moduleName, const CString &entry, bool flag) +{ + CString modulePath = bundleName + PathHelper::SLASH_TAG + moduleName; + CString abcFilePath = ModulePathHelper::ConcatPandaFilePath(moduleName); + std::shared_ptr jsPandaFile = + JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, abcFilePath, entry); + if (jsPandaFile == nullptr) { + LOG_FULL(FATAL) << "When the route jump, loading panda file failed. Current file is " << abcFilePath; + } + CString entryPoint = ModulePathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(), + abcFilePath, modulePath, entry); + JSRecordInfo recordInfo; + bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entryPoint, recordInfo); + if (!hasRecord) { + CString msg = "When the route jump, Cannot find module '" + entryPoint + "'"; + THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), Unexpected(false)); + } + ASSERT(jsPandaFile->IsModule(recordInfo)); + [[maybe_unused]] EcmaHandleScope scope(thread); + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle moduleRecord(thread->GlobalConstants()->GetHandledUndefined()); + ASSERT(!jsPandaFile->IsBundlePack()); + moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(abcFilePath, entryPoint); + SourceTextModule::Instantiate(thread, moduleRecord); + if (thread->HasPendingException()) { + return Unexpected(false); + } + JSHandle module = JSHandle::Cast(moduleRecord); + if (!flag) { + LOG_ECMA(INFO) << "Route jump to non-singleton page: " << entryPoint; + module->SetStatus(ModuleStatus::INSTANTIATED); + } else { + LOG_ECMA(INFO) << "Route jump to singleton page: " << entryPoint; + } + SourceTextModule::Evaluate(thread, module, nullptr, 0); + if (thread->HasPendingException()) { + return Unexpected(false); + } + return JSTaggedValue::Undefined(); +} } // namespace panda::ecmascript diff --git a/ecmascript/jspandafile/js_pandafile_executor.h b/ecmascript/jspandafile/js_pandafile_executor.h index 6e8faa01b..a8a044097 100644 --- a/ecmascript/jspandafile/js_pandafile_executor.h +++ b/ecmascript/jspandafile/js_pandafile_executor.h @@ -47,6 +47,9 @@ public: bool needUpdate = false); static Expected CommonExecuteBuffer(JSThread *thread, const CString &filename, const CString &entry, const JSPandaFile *jsPandaFile); + static Expected ExecuteAbcFileWithFlag(JSThread *thread, const CString &bundleName, + const CString &moduleName, const CString &entry, + bool flag); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_JSPANDAFILE_JS_PANDAFILE_EXECUTOR_H diff --git a/ecmascript/module/module_path_helper.h b/ecmascript/module/module_path_helper.h index 50858f0be..0e56a1011 100644 --- a/ecmascript/module/module_path_helper.h +++ b/ecmascript/module/module_path_helper.h @@ -239,7 +239,7 @@ public: * Before: moduleName * After: data/storage/el1/bundle/moduleName/ets/modules.abc */ - inline static CString ConcatPandaFilePath(CString &moduleName) + inline static CString ConcatPandaFilePath(const CString &moduleName) { if (moduleName.size() == 0) { return CString(); diff --git a/ecmascript/napi/include/jsnapi_expo.h b/ecmascript/napi/include/jsnapi_expo.h index ad79db946..072635d9e 100644 --- a/ecmascript/napi/include/jsnapi_expo.h +++ b/ecmascript/napi/include/jsnapi_expo.h @@ -1181,6 +1181,8 @@ public: static bool Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry, bool needUpdate = false); static bool Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry, const std::string &filename = "", bool needUpdate = false); + static bool ExecuteWithStatus(EcmaVM *vm, const std::string &bundleName, const std::string &moduleName, + const std::string &ohmurl, bool flag); // merge abc, execute module buffer static bool ExecuteModuleBuffer(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &filename = "", bool needUpdate = false); diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index ec50abac8..becf9c5b9 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -3403,6 +3403,23 @@ bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::s return true; } +bool JSNApi::ExecuteWithStatus(EcmaVM *vm, const std::string &bundleName, const std::string &moduleName, + const std::string &ohmurl, bool flag) +{ + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, false); + if (!ecmascript::JSPandaFileExecutor::ExecuteAbcFileWithFlag(thread, bundleName.c_str(), moduleName.c_str(), + ohmurl.c_str(), flag)) { + if (thread->HasPendingException()) { + thread->GetCurrentEcmaContext()->HandleUncaughtException(); + } + LOG_ECMA(ERROR) << "Cannot execute ark file with bundle name is'" << bundleName + << "' and module name is '" << moduleName + << "', entry is'" << ohmurl << "'" << std::endl; + return false; + } + return true; +} + // The security interface needs to be modified accordingly. bool JSNApi::ExecuteModuleBuffer(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &filename, bool needUpdate) -- Gitee From 4fdaf27d8c2c1901157a5323d1aba522d8ca1671 Mon Sep 17 00:00:00 2001 From: zhanheng Date: Wed, 20 Mar 2024 14:21:09 +0800 Subject: [PATCH 005/202] fix dump InvaliedValued Signed-off-by: z00522183 Change-Id: I46ee988994268169c6b60e4586883985575e2e01 --- ecmascript/dump.cpp | 204 +++++++++++++++++++++++++++++--------------- 1 file changed, 133 insertions(+), 71 deletions(-) diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 117d11896..44af97697 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -1776,9 +1776,11 @@ void JSAPITreeMap::Dump(std::ostream &os) const void JSAPITreeMap::DumpForSnapshot(std::vector &vec) const { - TaggedTreeMap *map = TaggedTreeMap::Cast(GetTreeMap().GetTaggedObject()); - vec.emplace_back("treemap", GetTreeMap()); - map->DumpForSnapshot(vec); + if (!(GetTreeMap().IsInvalidValue())) { + TaggedTreeMap *map = TaggedTreeMap::Cast(GetTreeMap().GetTaggedObject()); + vec.emplace_back("treemap", GetTreeMap()); + map->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } @@ -1800,10 +1802,13 @@ void JSAPITreeMapIterator::Dump(std::ostream &os) const void JSAPITreeMapIterator::DumpForSnapshot(std::vector &vec) const { - TaggedTreeMap *map = - TaggedTreeMap::Cast(JSAPITreeMap::Cast(GetIteratedMap().GetTaggedObject())->GetTreeMap().GetTaggedObject()); - vec.emplace_back("iteratedmap", GetIteratedMap()); - map->DumpForSnapshot(vec); + if (!(GetIteratedMap().IsInvalidValue())) { + TaggedTreeMap *map = + TaggedTreeMap::Cast(JSAPITreeMap::Cast(GetIteratedMap().GetTaggedObject())->GetTreeMap().GetTaggedObject()); + vec.emplace_back("iteratedmap", GetIteratedMap()); + map->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); JSObject::DumpForSnapshot(vec); @@ -1893,9 +1898,11 @@ void JSAPITreeSet::Dump(std::ostream &os) const void JSAPITreeSet::DumpForSnapshot(std::vector &vec) const { - TaggedTreeSet *set = TaggedTreeSet::Cast(GetTreeSet().GetTaggedObject()); - vec.emplace_back("treeset", GetTreeSet()); - set->DumpForSnapshot(vec); + if (!(GetTreeSet().IsInvalidValue())) { + TaggedTreeSet *set = TaggedTreeSet::Cast(GetTreeSet().GetTaggedObject()); + vec.emplace_back("treeset", GetTreeSet()); + set->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } @@ -1917,10 +1924,13 @@ void JSAPITreeSetIterator::Dump(std::ostream &os) const void JSAPITreeSetIterator::DumpForSnapshot(std::vector &vec) const { - TaggedTreeSet *set = - TaggedTreeSet::Cast(JSAPITreeSet::Cast(GetIteratedSet().GetTaggedObject())->GetTreeSet().GetTaggedObject()); - vec.emplace_back("iteratedset", GetIteratedSet()); - set->DumpForSnapshot(vec); + if (!(GetIteratedSet().IsInvalidValue())) { + TaggedTreeSet *set = + TaggedTreeSet::Cast(JSAPITreeSet::Cast(GetIteratedSet().GetTaggedObject())->GetTreeSet().GetTaggedObject()); + vec.emplace_back("iteratedset", GetIteratedSet()); + set->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); JSObject::DumpForSnapshot(vec); @@ -1985,9 +1995,12 @@ void JSAPIPlainArrayIterator::Dump(std::ostream &os) const void JSAPIPlainArrayIterator::DumpForSnapshot(std::vector &vec) const { - JSAPIPlainArray *array = JSAPIPlainArray::Cast(GetIteratedPlainArray().GetTaggedObject()); - vec.emplace_back("iteratedplainarray", GetIteratedPlainArray()); - array->DumpForSnapshot(vec); + if (!(GetIteratedPlainArray().IsInvalidValue())) { + JSAPIPlainArray *array = JSAPIPlainArray::Cast(GetIteratedPlainArray().GetTaggedObject()); + vec.emplace_back("iteratedplainarray", GetIteratedPlainArray()); + array->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); JSObject::DumpForSnapshot(vec); } @@ -2205,9 +2218,12 @@ void JSAPIHashMap::Dump(std::ostream &os) const void JSAPIHashMap::DumpForSnapshot(std::vector &vec) const { - TaggedHashArray *map = TaggedHashArray::Cast(GetTable().GetTaggedObject()); - vec.emplace_back("hashmap", GetTable()); - map->DumpForSnapshot(vec); + if (!(GetTable().IsInvalidValue())) { + TaggedHashArray *map = TaggedHashArray::Cast(GetTable().GetTaggedObject()); + vec.emplace_back("hashmap", GetTable()); + map->DumpForSnapshot(vec); + } + JSObject::DumpForSnapshot(vec); } @@ -2221,9 +2237,12 @@ void JSAPIHashSet::Dump(std::ostream &os) const void JSAPIHashSet::DumpForSnapshot(std::vector &vec) const { - TaggedHashArray *set = TaggedHashArray::Cast(GetTable().GetTaggedObject()); - vec.emplace_back("hashset", GetTable()); - set->DumpForSnapshot(vec); + if (!(GetTable().IsInvalidValue())) { + TaggedHashArray *set = TaggedHashArray::Cast(GetTable().GetTaggedObject()); + vec.emplace_back("hashset", GetTable()); + set->DumpForSnapshot(vec); + } + JSObject::DumpForSnapshot(vec); } @@ -2333,8 +2352,10 @@ void JSAPILinkedList::Dump(std::ostream &os) const void JSAPILinkedList::DumpForSnapshot(std::vector &vec) const { - TaggedDoubleList *list = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); - list->DumpForSnapshot(vec); + if (!(GetDoubleList().IsInvalidValue())) { + TaggedDoubleList *list = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + list->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } @@ -2352,9 +2373,12 @@ void JSAPILinkedListIterator::Dump(std::ostream &os) const void JSAPILinkedListIterator::DumpForSnapshot(std::vector &vec) const { - TaggedDoubleList *linkedList = TaggedDoubleList::Cast(GetIteratedLinkedList().GetTaggedObject()); - vec.emplace_back("iteratedlist", GetIteratedLinkedList()); - linkedList->DumpForSnapshot(vec); + if (!(GetIteratedLinkedList().IsInvalidValue())) { + TaggedDoubleList *linkedList = TaggedDoubleList::Cast(GetIteratedLinkedList().GetTaggedObject()); + vec.emplace_back("iteratedlist", GetIteratedLinkedList()); + linkedList->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); JSObject::DumpForSnapshot(vec); } @@ -4937,9 +4961,11 @@ void JSDate::DumpForSnapshot(std::vector &vec) const void JSMap::DumpForSnapshot(std::vector &vec) const { - LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject()); - vec.emplace_back("linkedmap", GetLinkedMap()); - map->DumpForSnapshot(vec); + if (!(GetLinkedMap().IsInvalidValue())) { + LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject()); + vec.emplace_back("linkedmap", GetLinkedMap()); + map->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } @@ -4956,9 +4982,12 @@ void JSForInIterator::DumpForSnapshot(std::vector &vec) const void JSMapIterator::DumpForSnapshot(std::vector &vec) const { - LinkedHashMap *map = LinkedHashMap::Cast(GetIteratedMap().GetTaggedObject()); - vec.emplace_back("iteratedmap", GetIteratedMap()); - map->DumpForSnapshot(vec); + if (!(GetIteratedMap().IsInvalidValue())) { + LinkedHashMap *map = LinkedHashMap::Cast(GetIteratedMap().GetTaggedObject()); + vec.emplace_back("iteratedmap", GetIteratedMap()); + map->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); JSObject::DumpForSnapshot(vec); @@ -4966,27 +4995,33 @@ void JSMapIterator::DumpForSnapshot(std::vector &vec) const void JSSet::DumpForSnapshot(std::vector &vec) const { - LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject()); - vec.emplace_back("linkedset", GetLinkedSet()); - set->DumpForSnapshot(vec); + if (!(GetLinkedSet().IsInvalidValue())) { + LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject()); + vec.emplace_back("linkedset", GetLinkedSet()); + set->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } void JSWeakMap::DumpForSnapshot(std::vector &vec) const { - LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject()); - vec.emplace_back("linkedmap", GetLinkedMap()); - map->DumpForSnapshot(vec); + if (!(GetLinkedMap().IsInvalidValue())) { + LinkedHashMap *map = LinkedHashMap::Cast(GetLinkedMap().GetTaggedObject()); + vec.emplace_back("linkedmap", GetLinkedMap()); + map->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } void JSWeakSet::DumpForSnapshot(std::vector &vec) const { - LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject()); - vec.emplace_back("linkeset", GetLinkedSet()); - set->DumpForSnapshot(vec); + if (!(GetLinkedSet().IsInvalidValue())) { + LinkedHashSet *set = LinkedHashSet::Cast(GetLinkedSet().GetTaggedObject()); + vec.emplace_back("linkeset", GetLinkedSet()); + set->DumpForSnapshot(vec); + } JSObject::DumpForSnapshot(vec); } @@ -5000,8 +5035,11 @@ void JSWeakRef::DumpForSnapshot(std::vector &vec) const void JSFinalizationRegistry::DumpForSnapshot(std::vector &vec) const { vec.emplace_back(CString("CleanupCallback"), GetCleanupCallback()); - LinkedHashMap *map = LinkedHashMap::Cast(GetMaybeUnregister().GetTaggedObject()); - map->DumpForSnapshot(vec); + if (!(GetMaybeUnregister().IsInvalidValue())) { + LinkedHashMap *map = LinkedHashMap::Cast(GetMaybeUnregister().GetTaggedObject()); + map->DumpForSnapshot(vec); + } + vec.emplace_back(CString("MaybeUnregister"), GetMaybeUnregister()); vec.emplace_back(CString("Next"), GetNext()); vec.emplace_back(CString("Prev"), GetPrev()); @@ -5016,9 +5054,12 @@ void CellRecord::DumpForSnapshot(std::vector &vec) const void JSSetIterator::DumpForSnapshot(std::vector &vec) const { - LinkedHashSet *set = LinkedHashSet::Cast(GetIteratedSet().GetTaggedObject()); - vec.emplace_back("iteratedset", GetIteratedSet()); - set->DumpForSnapshot(vec); + if (!(GetIteratedSet().IsInvalidValue())) { + LinkedHashSet *set = LinkedHashSet::Cast(GetIteratedSet().GetTaggedObject()); + vec.emplace_back("iteratedset", GetIteratedSet()); + set->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); JSObject::DumpForSnapshot(vec); @@ -5065,10 +5106,13 @@ void JSAPILightWeightMap::DumpForSnapshot(std::vector &vec) const void JSAPILightWeightMapIterator::DumpForSnapshot(std::vector &vec) const { - JSAPILightWeightMap *map = - JSAPILightWeightMap::Cast(GetIteratedLightWeightMap().GetTaggedObject()); - vec.emplace_back("iteratedmap", GetIteratedLightWeightMap()); - map->DumpForSnapshot(vec); + if (!(GetIteratedLightWeightMap().IsInvalidValue())) { + JSAPILightWeightMap *map = + JSAPILightWeightMap::Cast(GetIteratedLightWeightMap().GetTaggedObject()); + vec.emplace_back("iteratedmap", GetIteratedLightWeightMap()); + map->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); vec.emplace_back(CString("BitField"), JSTaggedValue(GetBitField())); @@ -5083,9 +5127,12 @@ void JSAPIQueue::DumpForSnapshot(std::vector &vec) const void JSAPIQueueIterator::DumpForSnapshot(std::vector &vec) const { - JSAPIQueue *queue = JSAPIQueue::Cast(GetIteratedQueue().GetTaggedObject()); - vec.emplace_back("iteratedqueue", GetIteratedQueue()); - queue->DumpForSnapshot(vec); + if (!(GetIteratedQueue().IsInvalidValue())) { + JSAPIQueue *queue = JSAPIQueue::Cast(GetIteratedQueue().GetTaggedObject()); + vec.emplace_back("iteratedqueue", GetIteratedQueue()); + queue->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); JSObject::DumpForSnapshot(vec); } @@ -5097,9 +5144,12 @@ void JSAPIDeque::DumpForSnapshot(std::vector &vec) const void JSAPIDequeIterator::DumpForSnapshot(std::vector &vec) const { - JSAPIDeque *deque = JSAPIDeque::Cast(GetIteratedDeque().GetTaggedObject()); - vec.emplace_back("iterateddeque", GetIteratedDeque()); - deque->DumpForSnapshot(vec); + if (!(GetIteratedDeque().IsInvalidValue())) { + JSAPIDeque *deque = JSAPIDeque::Cast(GetIteratedDeque().GetTaggedObject()); + vec.emplace_back("iterateddeque", GetIteratedDeque()); + deque->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); JSObject::DumpForSnapshot(vec); } @@ -5121,10 +5171,13 @@ void JSAPILightWeightSet::DumpForSnapshot(std::vector &vec) const void JSAPILightWeightSetIterator::DumpForSnapshot(std::vector &vec) const { - JSAPILightWeightSet *set = - JSAPILightWeightSet::Cast(GetIteratedLightWeightSet().GetTaggedObject()); - vec.emplace_back("iteratedset", GetIteratedLightWeightSet()); - set->DumpForSnapshot(vec); + if (!(GetIteratedLightWeightSet().IsInvalidValue())) { + JSAPILightWeightSet *set = + JSAPILightWeightSet::Cast(GetIteratedLightWeightSet().GetTaggedObject()); + vec.emplace_back("iteratedset", GetIteratedLightWeightSet()); + set->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); JSObject::DumpForSnapshot(vec); @@ -5137,18 +5190,24 @@ void JSAPIStack::DumpForSnapshot(std::vector &vec) const void JSAPIStackIterator::DumpForSnapshot(std::vector &vec) const { - JSAPIStack *stack = JSAPIStack::Cast(GetIteratedStack().GetTaggedObject()); - vec.emplace_back("iteratedstack", GetIteratedStack()); - stack->DumpForSnapshot(vec); + if (!(GetIteratedStack().IsInvalidValue())) { + JSAPIStack *stack = JSAPIStack::Cast(GetIteratedStack().GetTaggedObject()); + vec.emplace_back("iteratedstack", GetIteratedStack()); + stack->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); JSObject::DumpForSnapshot(vec); } void JSArrayIterator::DumpForSnapshot(std::vector &vec) const { - JSArray *array = JSArray::Cast(GetIteratedArray().GetTaggedObject()); - vec.emplace_back("iteratedarray", GetIteratedArray()); - array->DumpForSnapshot(vec); + if (!(GetIteratedArray().IsInvalidValue())) { + JSArray *array = JSArray::Cast(GetIteratedArray().GetTaggedObject()); + vec.emplace_back("iteratedarray", GetIteratedArray()); + array->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); vec.emplace_back(CString("IterationKind"), JSTaggedValue(static_cast(GetIterationKind()))); vec.emplace_back(CString("BitField"), JSTaggedValue(GetBitField())); @@ -5162,9 +5221,12 @@ void JSAPIVector::DumpForSnapshot(std::vector &vec) const void JSAPIVectorIterator::DumpForSnapshot(std::vector &vec) const { - JSAPIVector *vector = JSAPIVector::Cast(GetIteratedVector().GetTaggedObject()); - vec.emplace_back("iteratedvector", GetIteratedVector()); - vector->DumpForSnapshot(vec); + if (!(GetIteratedVector().IsInvalidValue())) { + JSAPIVector *vector = JSAPIVector::Cast(GetIteratedVector().GetTaggedObject()); + vec.emplace_back("iteratedvector", GetIteratedVector()); + vector->DumpForSnapshot(vec); + } + vec.emplace_back(CString("NextIndex"), JSTaggedValue(GetNextIndex())); JSObject::DumpForSnapshot(vec); } -- Gitee From 8757b6215ca113e59ff01bb30712d1f1b37b339e Mon Sep 17 00:00:00 2001 From: Like Date: Wed, 20 Mar 2024 15:40:20 +0800 Subject: [PATCH 006/202] avoid crash caused by ic slot Signed-off-by: Like Change-Id: I6c2a3c06afe3c04990a8b6fc82601af881462b80 --- ecmascript/compiler/stub_builder-inl.h | 5 ++++ ecmascript/compiler/stub_builder.cpp | 32 +++++++++++++----------- ecmascript/compiler/stub_builder.h | 1 + ecmascript/pgo_profiler/pgo_profiler.cpp | 3 +-- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index fb4e9699a..f8640554a 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -707,6 +707,11 @@ inline GateRef StubBuilder::TaggedIsJSArray(GateRef x) return env_->GetBuilder()->TaggedIsJSArray(x); } +inline GateRef StubBuilder::IsTaggedArray(GateRef x) +{ + return env_->GetBuilder()->IsTaggedArray(x); +} + inline GateRef StubBuilder::TaggedIsAsyncGeneratorObject(GateRef x) { return env_->GetBuilder()->TaggedIsAsyncGeneratorObject(x); diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index d1fba4c74..5a09d3a5e 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -1674,23 +1674,27 @@ GateRef StubBuilder::CheckPolyHClass(GateRef cachedValue, GateRef hclass) BRANCH(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak); Bind(&cachedValueNotWeak); { - GateRef length = GetLengthOfTaggedArray(cachedValue); - Jump(&loopHead); - LoopBegin(&loopHead); + Label isTaggedArray(env); + Branch(IsTaggedArray(cachedValue), &isTaggedArray, &exit); + Bind(&isTaggedArray); { - BRANCH(Int32UnsignedLessThan(*i, length), &iLessLength, &exit); - Bind(&iLessLength); + GateRef length = GetLengthOfTaggedArray(cachedValue); + Jump(&loopHead); + LoopBegin(&loopHead); { - GateRef element = GetValueFromTaggedArray(cachedValue, *i); - BRANCH(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd); - Bind(&hasHclass); - result = GetValueFromTaggedArray(cachedValue, - Int32Add(*i, Int32(1))); - Jump(&exit); + BRANCH(Int32UnsignedLessThan(*i, length), &iLessLength, &exit); + Bind(&iLessLength); + { + GateRef element = GetValueFromTaggedArray(cachedValue, *i); + BRANCH(Equal(LoadObjectFromWeakRef(element), hclass), &hasHclass, &loopEnd); + Bind(&hasHclass); + result = GetValueFromTaggedArray(cachedValue, Int32Add(*i, Int32(1))); + Jump(&exit); + } + Bind(&loopEnd); + i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot + LoopEnd(&loopHead); } - Bind(&loopEnd); - i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot - LoopEnd(&loopHead); } } Bind(&exit); diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index a9f3ba62b..f82de7790 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -236,6 +236,7 @@ public: GateRef InYoungGeneration(GateRef region); GateRef TaggedIsGeneratorObject(GateRef x); GateRef TaggedIsJSArray(GateRef x); + GateRef IsTaggedArray(GateRef x); GateRef TaggedIsAsyncGeneratorObject(GateRef x); GateRef TaggedIsJSGlobalObject(GateRef x); GateRef TaggedIsWeak(GateRef x); diff --git a/ecmascript/pgo_profiler/pgo_profiler.cpp b/ecmascript/pgo_profiler/pgo_profiler.cpp index e72d30ecf..26154a879 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler.cpp @@ -562,8 +562,7 @@ void PGOProfiler::ProfileBytecode(ApEntityId abcId, const CString &recordName, J break; } case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8: - case EcmaOpcode::STTHISBYNAME_IMM8_ID16: - case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: { + case EcmaOpcode::STTHISBYNAME_IMM8_ID16: { uint8_t slotId = READ_INST_8_0(); CHECK_SLOTID_BREAK(slotId); DumpICByName(abcId, recordName, methodId, bcOffset, slotId, profileTypeInfo, BCType::STORE); -- Gitee From a238795bf70d51d738ebc84df94b8b9f4b676344 Mon Sep 17 00:00:00 2001 From: Sidorov Aleksei Date: Wed, 13 Mar 2024 20:01:01 +0800 Subject: [PATCH 007/202] Inline Math.Exp* builtins Signed-off-by: Sidorov Aleksei Change-Id: Icff51c7fb4f34a2b1c62392d3229fb55114f38b6 --- ecmascript/builtins/builtins_math.h | 4 +- .../builtins/builtins_call_signature.h | 8 ++ ecmascript/compiler/call_signature.cpp | 2 + ecmascript/compiler/call_signature.h | 2 + ecmascript/compiler/circuit_builder.h | 1 + .../compiler/codegen/llvm/llvm_ir_builder.cpp | 42 ++++++ ecmascript/compiler/ir_builder.h | 1 + ecmascript/compiler/mcr_opcodes.h | 2 + .../compiler/native_inline_lowering.cpp | 6 + .../compiler/number_speculative_retype.cpp | 2 + .../compiler/typed_native_inline_lowering.cpp | 21 +++ .../compiler/typed_native_inline_lowering.h | 1 + ecmascript/global_env_constants.h | 2 + ecmascript/stubs/runtime_stubs.cpp | 10 ++ ecmascript/stubs/runtime_stubs.h | 4 + test/aottest/builtin_inlining/math/BUILD.gn | 2 + .../builtin_inlining/math/Exp/BUILD.gn | 24 ++++ .../math/Exp/builtinMathExp.ts | 136 ++++++++++++++++++ .../math/Exp/expect_output.txt | 56 ++++++++ .../math/Exp/pgo_expect_output.txt | 45 ++++++ .../builtin_inlining/math/Expm1/BUILD.gn | 24 ++++ .../math/Expm1/builtinMathExpm1.ts | 136 ++++++++++++++++++ .../math/Expm1/expect_output.txt | 56 ++++++++ .../math/Expm1/pgo_expect_output.txt | 45 ++++++ 24 files changed, 630 insertions(+), 2 deletions(-) create mode 100644 test/aottest/builtin_inlining/math/Exp/BUILD.gn create mode 100644 test/aottest/builtin_inlining/math/Exp/builtinMathExp.ts create mode 100644 test/aottest/builtin_inlining/math/Exp/expect_output.txt create mode 100644 test/aottest/builtin_inlining/math/Exp/pgo_expect_output.txt create mode 100644 test/aottest/builtin_inlining/math/Expm1/BUILD.gn create mode 100644 test/aottest/builtin_inlining/math/Expm1/builtinMathExpm1.ts create mode 100644 test/aottest/builtin_inlining/math/Expm1/expect_output.txt create mode 100644 test/aottest/builtin_inlining/math/Expm1/pgo_expect_output.txt diff --git a/ecmascript/builtins/builtins_math.h b/ecmascript/builtins/builtins_math.h index 4f63f6b02..349451f89 100644 --- a/ecmascript/builtins/builtins_math.h +++ b/ecmascript/builtins/builtins_math.h @@ -47,8 +47,8 @@ V("clz32", Clz32, 1, INVALID) /* Math.clz32 ( x ) */ \ V("cos", Cos, 1, MathCos) /* Math.cos ( x ) */ \ V("cosh", Cosh, 1, MathCosh) /* Math.cosh ( x ) */ \ - V("exp", Exp, 1, INVALID) /* Math.exp ( x ) */ \ - V("expm1", Expm1, 1, INVALID) /* Math.expm1 ( x ) */ \ + V("exp", Exp, 1, MathExp) /* Math.exp ( x ) */ \ + V("expm1", Expm1, 1, MathExpm1) /* Math.expm1 ( x ) */ \ V("floor", Floor, 1, FLOOR) /* Math.floor ( x ) */ \ V("fround", Fround, 1, INVALID) /* Math.fround ( x ) */ \ V("hypot", Hypot, 2, INVALID) /* Math.hypot ( ...args ) */ \ diff --git a/ecmascript/compiler/builtins/builtins_call_signature.h b/ecmascript/compiler/builtins/builtins_call_signature.h index 4d4db41f1..96c5fe37b 100644 --- a/ecmascript/compiler/builtins/builtins_call_signature.h +++ b/ecmascript/compiler/builtins/builtins_call_signature.h @@ -152,6 +152,8 @@ namespace panda::ecmascript::kungfu { V(MathLog2) \ V(MathLog10) \ V(MathLog1p) \ + V(MathExp) \ + V(MathExpm1) \ V(MathPow) \ V(MathAbs) \ V(TYPED_BUILTINS_INLINE_FIRST = MathAcos) \ @@ -305,6 +307,10 @@ public: return ConstantIndex::MATH_LOG10_INDEX; case BuiltinsStubCSigns::ID::MathLog1p: return ConstantIndex::MATH_LOG1P_INDEX; + case BuiltinsStubCSigns::ID::MathExp: + return ConstantIndex::MATH_EXP_INDEX; + case BuiltinsStubCSigns::ID::MathExpm1: + return ConstantIndex::MATH_EXPM1_INDEX; case BuiltinsStubCSigns::ID::MathPow: return ConstantIndex::MATH_POW_INDEX; case BuiltinsStubCSigns::ID::FLOOR: @@ -357,6 +363,8 @@ public: {"Log2", MathLog2}, {"Log10", MathLog10}, {"Log1p", MathLog1p}, + {"Exp", MathExp}, + {"Expm1", MathExpm1}, {"sqrt", SQRT}, {"abs", MathAbs}, {"pow", MathPow}, diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index 966c557c3..7710b4c4c 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -1907,6 +1907,8 @@ DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatSin) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatSinh) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatTan) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatTanh) +DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatExp) +DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatExpm1) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatFloor) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatLog) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatLog2) diff --git a/ecmascript/compiler/call_signature.h b/ecmascript/compiler/call_signature.h index f6529e6f6..9fd134361 100644 --- a/ecmascript/compiler/call_signature.h +++ b/ecmascript/compiler/call_signature.h @@ -459,6 +459,8 @@ private: V(FloatLog2) \ V(FloatLog10) \ V(FloatLog1p) \ + V(FloatExp) \ + V(FloatExpm1) \ V(FloatFloor) \ V(FloatPow) \ V(FindElementWithCache) \ diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 94377cf46..1d3c431ad 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -61,6 +61,7 @@ class PostSchedule; V(Int64Add, Add, MachineType::I64) \ V(DoubleAdd, Add, MachineType::F64) \ V(PtrAdd, Add, MachineType::ARCH) \ + V(DoubleExp, Exp, MachineType::F64) \ V(Int16Sub, Sub, MachineType::I16) \ V(Int32Sub, Sub, MachineType::I32) \ V(Int64Sub, Sub, MachineType::I64) \ diff --git a/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp b/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp index 31355bd2b..94cc91f73 100644 --- a/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp +++ b/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp @@ -45,6 +45,8 @@ #endif #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IRBuilder.h" #if defined(__clang__) #pragma clang diagnostic pop @@ -204,6 +206,7 @@ void LLVMIRBuilder::InitializeHandlers() {OpCode::MUL_WITH_OVERFLOW, &LLVMIRBuilder::HandleMulWithOverflow}, {OpCode::EXTRACT_VALUE, &LLVMIRBuilder::HandleExtractValue}, {OpCode::SQRT, &LLVMIRBuilder::HandleSqrt}, + {OpCode::EXP, &LLVMIRBuilder::HandleExp}, {OpCode::READSP, &LLVMIRBuilder::HandleReadSp}, {OpCode::FINISH_ALLOCATE, &LLVMIRBuilder::HandleFinishAllocate}, }; @@ -1981,6 +1984,45 @@ void LLVMIRBuilder::VisitSqrt(GateRef gate, GateRef e1) } } +void LLVMIRBuilder::HandleExp(GateRef gate) +{ + GateRef base = acc_.GetIn(gate, 0U); + GateRef power = acc_.GetIn(gate, 1U); + VisitExp(gate, base, power); +} + +void LLVMIRBuilder::VisitExp([[maybe_unused]] GateRef gate, [[maybe_unused]] GateRef e1, [[maybe_unused]] GateRef e2) +{ +#ifdef SUPPORT_LLVM_INTRINSICS_WITH_CALLS + llvm::Value *e1Value = llvm::unwrap(GetLValue(e1)); + llvm::Value *e2Value = llvm::unwrap(GetLValue(e2)); + + [[maybe_unused]] auto machineType = acc_.GetMachineType(gate); + ASSERT(machineType == MachineType::F64); + ASSERT(acc_.GetMachineType(e1) == machineType); + ASSERT(acc_.GetMachineType(e2) == machineType); + + llvm::Value *result = nullptr; + + constexpr double one = 1.0; + if (acc_.IsConstant(e1) && acc_.GetFloat64FromConstant(e1) == std::exp(one)) { + llvm::Intrinsic::ID llvmId = llvm::Intrinsic::exp; + result = llvm::unwrap(builder_)->CreateUnaryIntrinsic(llvmId, e2Value); + } else { + llvm::Intrinsic::ID llvmId = llvm::Intrinsic::pow; + result = llvm::unwrap(builder_)->CreateBinaryIntrinsic(llvmId, e1Value, e2Value); + } + + Bind(gate, llvm::wrap(result)); + + if (IsLogEnabled()) { + SetDebugInfo(gate, llvm::wrap(result)); + } +#else + UNREACHABLE(); +#endif +} + LLVMIntPredicate LLVMIRBuilder::ConvertLLVMPredicateFromICMP(ICmpCondition cond) { switch (cond) { diff --git a/ecmascript/compiler/ir_builder.h b/ecmascript/compiler/ir_builder.h index f6e712cfc..2f9251e2b 100644 --- a/ecmascript/compiler/ir_builder.h +++ b/ecmascript/compiler/ir_builder.h @@ -102,6 +102,7 @@ enum class CallExceptionKind : bool { V(MulWithOverflow, (GateRef gate, GateRef e1, GateRef e2)) \ V(ExtractValue, (GateRef gate, GateRef e1, GateRef e2)) \ V(Sqrt, (GateRef gate, GateRef e1)) \ + V(Exp, (GateRef gate, GateRef e1, GateRef e2)) \ V(ReadSp, (GateRef gate)) \ V(FinishAllocate, (GateRef gate, GateRef e1)) diff --git a/ecmascript/compiler/mcr_opcodes.h b/ecmascript/compiler/mcr_opcodes.h index dd1b8f7f2..5c02e9a00 100644 --- a/ecmascript/compiler/mcr_opcodes.h +++ b/ecmascript/compiler/mcr_opcodes.h @@ -78,6 +78,8 @@ namespace panda::ecmascript::kungfu { V(MathLog2, MATH_LOG2, GateFlags::NO_WRITE, 1, 1, 1) \ V(MathLog10, MATH_LOG10, GateFlags::NO_WRITE, 1, 1, 1) \ V(MathLog1p, MATH_LOG1P, GateFlags::NO_WRITE, 1, 1, 1) \ + V(MathExp, MATH_EXP, GateFlags::NO_WRITE, 1, 1, 1) \ + V(MathExpm1, MATH_EXPM1, GateFlags::NO_WRITE, 1, 1, 1) \ V(MathAbs, MATH_ABS, GateFlags::NO_WRITE, 1, 1, 1) \ V(MathPow, MATH_POW, GateFlags::NO_WRITE, 1, 1, 2) \ MCR_BINARY_GATE_META_DATA_CACHE_LIST(V) diff --git a/ecmascript/compiler/native_inline_lowering.cpp b/ecmascript/compiler/native_inline_lowering.cpp index 2b6c78a58..a1e60f10a 100644 --- a/ecmascript/compiler/native_inline_lowering.cpp +++ b/ecmascript/compiler/native_inline_lowering.cpp @@ -116,6 +116,12 @@ void NativeInlineLowering::RunNativeInlineLowering() case BuiltinsStubCSigns::ID::MathLog1p: TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog1p()); break; + case BuiltinsStubCSigns::ID::MathExp: + TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExp()); + break; + case BuiltinsStubCSigns::ID::MathExpm1: + TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExpm1()); + break; case BuiltinsStubCSigns::ID::MathPow: TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathPow()); break; diff --git a/ecmascript/compiler/number_speculative_retype.cpp b/ecmascript/compiler/number_speculative_retype.cpp index c82280355..c65aa729c 100644 --- a/ecmascript/compiler/number_speculative_retype.cpp +++ b/ecmascript/compiler/number_speculative_retype.cpp @@ -137,6 +137,8 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate) case OpCode::MATH_LOG2: case OpCode::MATH_LOG10: case OpCode::MATH_LOG1P: + case OpCode::MATH_EXP: + case OpCode::MATH_EXPM1: case OpCode::MATH_ACOS: case OpCode::MATH_ACOSH: case OpCode::MATH_ASIN: diff --git a/ecmascript/compiler/typed_native_inline_lowering.cpp b/ecmascript/compiler/typed_native_inline_lowering.cpp index b242f02ae..28365996b 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.cpp +++ b/ecmascript/compiler/typed_native_inline_lowering.cpp @@ -42,6 +42,12 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate) case OpCode::MATH_LOG1P: LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatLog1p)); break; + case OpCode::MATH_EXP: + LowerMathExp(gate); + break; + case OpCode::MATH_EXPM1: + LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatExpm1)); + break; case OpCode::MATH_SINH: LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatSinh)); break; @@ -115,6 +121,21 @@ void TypedNativeInlineLowering::LowerMathPow(GateRef gate) acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } +void TypedNativeInlineLowering::LowerMathExp(GateRef gate) +{ +#ifdef SUPPORT_LLVM_INTRINSICS_WITH_CALLS + Environment env(gate, circuit_, &builder_); + constexpr double one = 1.0; + GateRef base = builder_.Double(std::exp(one)); + GateRef power = acc_.GetValueIn(gate, 0U); + + GateRef exp = builder_.DoubleExp(base, power); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), exp); +#else + LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatExp)); +#endif +} + template void TypedNativeInlineLowering::LowerGeneralUnaryMath(GateRef gate, RuntimeStubCSigns::ID stubId) { diff --git a/ecmascript/compiler/typed_native_inline_lowering.h b/ecmascript/compiler/typed_native_inline_lowering.h index 42da36aa2..22a0d2453 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.h +++ b/ecmascript/compiler/typed_native_inline_lowering.h @@ -42,6 +42,7 @@ private: void LowerMathAtan2(GateRef gate); void LowerAbs(GateRef gate); void LowerMathPow(GateRef gate); + void LowerMathExp(GateRef gate); private: Circuit* circuit_ {nullptr}; diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index e68f19a87..b637c4612 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -169,6 +169,8 @@ class ObjectFactory; V(JSTaggedValue, MathLog2, MATH_LOG2_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathLog10, MATH_LOG10_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathLog1p, MATH_LOG1P_INDEX, ecma_roots_special) \ + V(JSTaggedValue, MathExp, MATH_EXP_INDEX, ecma_roots_special) \ + V(JSTaggedValue, MathExpm1, MATH_EXPM1_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathAbs, MATH_ABS_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathPow, MATH_POW_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathFloorFunction, MATH_FLOOR_FUNCTION_INDEX, ecma_roots_special) \ diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index b7a668be4..8ac959e64 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -2976,6 +2976,16 @@ double RuntimeStubs::FloatLog1p(double x) return std::log1p(x); } +double RuntimeStubs::FloatExp(double x) +{ + return std::exp(x); +} + +double RuntimeStubs::FloatExpm1(double x) +{ + return std::expm1(x); +} + double RuntimeStubs::FloatPow(double base, double exp) { return std::pow(base, exp); diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 2c44a0f26..42e5d8bd1 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -134,6 +134,8 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co V(FloatLog2) \ V(FloatLog10) \ V(FloatLog1p) \ + V(FloatExp) \ + V(FloatExpm1) \ V(FloatFloor) \ V(FloatPow) \ V(FindElementWithCache) \ @@ -493,6 +495,8 @@ public: static double FloatLog2(double x); static double FloatLog10(double x); static double FloatLog1p(double x); + static double FloatExp(double x); + static double FloatExpm1(double x); static double FloatPow(double base, double exp); static int32_t FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass, JSTaggedType key, int32_t num); diff --git a/test/aottest/builtin_inlining/math/BUILD.gn b/test/aottest/builtin_inlining/math/BUILD.gn index 538ba5a51..c1120b86a 100644 --- a/test/aottest/builtin_inlining/math/BUILD.gn +++ b/test/aottest/builtin_inlining/math/BUILD.gn @@ -27,6 +27,8 @@ group("ark_aot_builtin_inlining_math_test") { "Log2", "Log10", "Log1p", + "Exp", + "Expm1", "Sin", "Sinh", "Tan", diff --git a/test/aottest/builtin_inlining/math/Exp/BUILD.gn b/test/aottest/builtin_inlining/math/Exp/BUILD.gn new file mode 100644 index 000000000..1ef12caba --- /dev/null +++ b/test/aottest/builtin_inlining/math/Exp/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("builtinMathExp") { + is_enable_pgo = true + is_only_typed_path = true + is_test_llvm_only = true + is_enable_opt_inlining = true + is_enable_trace_deopt = true + log_option = " --log-info=trace" + deps = [] +} diff --git a/test/aottest/builtin_inlining/math/Exp/builtinMathExp.ts b/test/aottest/builtin_inlining/math/Exp/builtinMathExp.ts new file mode 100644 index 000000000..b55358c17 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Exp/builtinMathExp.ts @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare interface ArkTools { + isAOTCompiled(args: any): boolean; +} +declare function print(arg:any):string; + +function printZero(x: any) { + if (Object.is(x, -0)) { + print("-0"); + } else { + print(x); + } +} + +function replace(a : number) +{ + return a; +} + +// Use try to prevent inlining to main +function printExp(x: any) { + try { + print(Math.exp(x)); + } finally { + } +} + +let doubleObj = { + valueOf: () => { return 2.7; } +} + +let nanObj = { + valueOf: () => { return "something"; } +} + +let obj = { + valueOf: () => { + print("obj.valueOf") + return -23; + } +}; + +// Check without params +print(Math.exp()); // NaN + +// Check with single param +print(Math.exp(0)); // 1 +print(Math.exp(-0)); // 1 +print(Math.exp(1)); // 2.718281828459045 +print(Math.exp(-100)); // 3.720075976020836e-44 +print(Math.exp(100)); // 2.6881171418161356e+43 +print(Math.exp(10e-10)); // 1.000000001 + +// Check with special float params +printZero(Math.exp(-Infinity)); // 0 +print(Math.exp(Infinity)); // Infinity +print(Math.exp(NaN)); // NaN + +// Check with 2 params +print(Math.exp(1, 1)); // 2.718281828459045 + +// Check with 3 params +print(Math.exp(1, 1, 1)); // 2.718281828459045 + +// Check with 4 params +print(Math.exp(1, 1, 1, 1)); // 2.718281828459045 + +// Check with 5 params +print(Math.exp(1, 1, 1, 1, 1)); // 2.718281828459045 + +try { + print(Math.exp(1)); // 2.718281828459045 +} catch(e) {} + +// Replace standart builtin +let trueExp = Math.exp +Math.exp = replace +print(Math.exp(111)); // 111 +Math.exp = trueExp + +print(Math.exp(1)); // 2.718281828459045 + +// Call standart builtin with non-number param +// Check Type: NotNumber1 +printExp("1"); // 2.718281828459045 +// Check Type: NotNumber1 +printExp("NaN"); // NaN +// Check Type: NotNumber1 +printExp("abc"); // NaN + +if (ArkTools.isAOTCompiled(printExp)) { + // Replace standard builtin after call to standard builtin was profiled + Math.exp = replace +} + +// Check Type: NotCallTarget1 +printExp(1); // 2.718281828459045 +// Check Type: NotCallTarget1 +printExp(2); // 7.38905609893065 +// Check Type: NotCallTarget1 +printExp("1"); // 2.718281828459045 +// Check Type: NotCallTarget1 +printExp("2"); // 7.38905609893065 + +Math.exp = trueExp + +// Check IR correctness inside try-block +try { + print(Math.exp(1)); //: 2.718281828459045 + print(Math.exp(1, 2)); //: 2.718281828459045 + printExp(1, 2); //: 2.718281828459045 + // Check Type: NotNumber1 + printExp("abc", 3e3); //: NaN +} catch (e) { +} + +// Check Type: NotNumber1 +printExp(obj); // 1.026187963170189e-10 +// Check Type: NotNumber1 +printExp(doubleObj); // 14.879731724872837 +// Check Type: NotNumber1 +printExp(nanObj); // NaN diff --git a/test/aottest/builtin_inlining/math/Exp/expect_output.txt b/test/aottest/builtin_inlining/math/Exp/expect_output.txt new file mode 100644 index 000000000..6c6122f24 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Exp/expect_output.txt @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +NaN +1 +1 +2.718281828459045 +3.720075976020836e-44 +2.6881171418161356e+43 +1.000000001 +0 +Infinity +NaN +2.718281828459045 +2.718281828459045 +2.718281828459045 +2.718281828459045 +2.718281828459045 +111 +2.718281828459045 +[trace] Check Type: NotNumber1 +2.718281828459045 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotCallTarget1 +1 +[trace] Check Type: NotCallTarget1 +2 +[trace] Check Type: NotCallTarget1 +1 +[trace] Check Type: NotCallTarget1 +2 +2.718281828459045 +2.718281828459045 +2.718281828459045 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotNumber1 +obj.valueOf +1.026187963170189e-10 +[trace] Check Type: NotNumber1 +14.879731724872837 +[trace] Check Type: NotNumber1 +NaN diff --git a/test/aottest/builtin_inlining/math/Exp/pgo_expect_output.txt b/test/aottest/builtin_inlining/math/Exp/pgo_expect_output.txt new file mode 100644 index 000000000..402ad84c7 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Exp/pgo_expect_output.txt @@ -0,0 +1,45 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +NaN +1 +1 +2.718281828459045 +3.720075976020836e-44 +2.6881171418161356e+43 +1.000000001 +0 +Infinity +NaN +2.718281828459045 +2.718281828459045 +2.718281828459045 +2.718281828459045 +2.718281828459045 +111 +2.718281828459045 +2.718281828459045 +NaN +NaN +2.718281828459045 +7.38905609893065 +2.718281828459045 +7.38905609893065 +2.718281828459045 +2.718281828459045 +2.718281828459045 +NaN +obj.valueOf +1.026187963170189e-10 +14.879731724872837 +NaN diff --git a/test/aottest/builtin_inlining/math/Expm1/BUILD.gn b/test/aottest/builtin_inlining/math/Expm1/BUILD.gn new file mode 100644 index 000000000..32023ace2 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Expm1/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("builtinMathExpm1") { + is_enable_pgo = true + is_only_typed_path = true + is_test_llvm_only = true + is_enable_opt_inlining = true + is_enable_trace_deopt = true + log_option = " --log-info=trace" + deps = [] +} diff --git a/test/aottest/builtin_inlining/math/Expm1/builtinMathExpm1.ts b/test/aottest/builtin_inlining/math/Expm1/builtinMathExpm1.ts new file mode 100644 index 000000000..ea18d4d0c --- /dev/null +++ b/test/aottest/builtin_inlining/math/Expm1/builtinMathExpm1.ts @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare interface ArkTools { + isAOTCompiled(args: any): boolean; +} +declare function print(arg:any):string; + +function printZero(x: any) { + if (Object.is(x, -0)) { + print("-0"); + } else { + print(x); + } +} + +function replace(a : number) +{ + return a; +} + +// Use try to prevent inlining to main +function printExpm1(x: any) { + try { + print(Math.expm1(x)); + } finally { + } +} + +let doubleObj = { + valueOf: () => { return 2.7; } +} + +let nanObj = { + valueOf: () => { return "something"; } +} + +let obj = { + valueOf: () => { + print("obj.valueOf") + return -23; + } +}; + +// Check without params +print(Math.expm1()); // NaN + +// Check with single param +printZero(Math.expm1(0)); // 0 +printZero(Math.expm1(-0)); // -0 +print(Math.expm1(1)); // 1.718281828459045 +print(Math.expm1(-100)); // -1 +print(Math.expm1(100)); // 2.6881171418161356e+43 +print(Math.expm1(10e-10)); // 1.0000000005000001e-9 + +// Check with special float params +print(Math.expm1(-Infinity)); // -1 +print(Math.expm1(Infinity)); // Infinity +print(Math.expm1(NaN)); // NaN + +// Check with 2 params +print(Math.expm1(1, 1)); // 1.718281828459045 + +// Check with 3 params +print(Math.expm1(1, 1, 1)); // 1.718281828459045 + +// Check with 4 params +print(Math.expm1(1, 1, 1, 1)); // 1.718281828459045 + +// Check with 5 params +print(Math.expm1(1, 1, 1, 1, 1)); // 1.718281828459045 + +try { + print(Math.expm1(1)); // 1.718281828459045 +} catch(e) {} + +// Replace standart builtin +let trueExpm1 = Math.expm1 +Math.expm1 = replace +print(Math.expm1(111)); // 111 +Math.expm1 = trueExpm1 + +print(Math.expm1(1)); // 1.718281828459045 + +// Call standart builtin with non-number param +// Check Type: NotNumber1 +printExpm1("1"); // 1.718281828459045 +// Check Type: NotNumber1 +printExpm1("NaN"); // NaN +// Check Type: NotNumber1 +printExpm1("abc"); // NaN + +if (ArkTools.isAOTCompiled(printExpm1)) { + // Replace standard builtin after call to standard builtin was profiled + Math.expm1 = replace +} + +// Check Type: NotCallTarget1 +printExpm1(1); // 1.718281828459045 +// Check Type: NotCallTarget1 +printExpm1(2); // 6.38905609893065 +// Check Type: NotCallTarget1 +printExpm1("1"); // 1.718281828459045 +// Check Type: NotCallTarget1 +printExpm1("2"); // 6.38905609893065 + +Math.expm1 = trueExpm1 + +// Check IR correctness inside try-block +try { + print(Math.expm1(1)); //: 1.718281828459045 + print(Math.expm1(1, 2)); //: 1.718281828459045 + printExpm1(1, 2); //: 1.718281828459045 + // Check Type: NotNumber1 + printExpm1("abc", 3e3); //: NaN +} catch (e) { +} + +// Check Type: NotNumber1 +printExpm1(obj); // -0.9999999998973812 +// Check Type: NotNumber1 +printExpm1(doubleObj); // 13.879731724872837 +// Check Type: NotNumber1 +printExpm1(nanObj); // NaN diff --git a/test/aottest/builtin_inlining/math/Expm1/expect_output.txt b/test/aottest/builtin_inlining/math/Expm1/expect_output.txt new file mode 100644 index 000000000..9ede40e9b --- /dev/null +++ b/test/aottest/builtin_inlining/math/Expm1/expect_output.txt @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +NaN +0 +-0 +1.718281828459045 +-1 +2.6881171418161356e+43 +1.0000000005000001e-9 +-1 +Infinity +NaN +1.718281828459045 +1.718281828459045 +1.718281828459045 +1.718281828459045 +1.718281828459045 +111 +1.718281828459045 +[trace] Check Type: NotNumber1 +1.718281828459045 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotCallTarget1 +1 +[trace] Check Type: NotCallTarget1 +2 +[trace] Check Type: NotCallTarget1 +1 +[trace] Check Type: NotCallTarget1 +2 +1.718281828459045 +1.718281828459045 +1.718281828459045 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotNumber1 +obj.valueOf +-0.9999999998973812 +[trace] Check Type: NotNumber1 +13.879731724872837 +[trace] Check Type: NotNumber1 +NaN diff --git a/test/aottest/builtin_inlining/math/Expm1/pgo_expect_output.txt b/test/aottest/builtin_inlining/math/Expm1/pgo_expect_output.txt new file mode 100644 index 000000000..0cb0b6e9d --- /dev/null +++ b/test/aottest/builtin_inlining/math/Expm1/pgo_expect_output.txt @@ -0,0 +1,45 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +NaN +0 +-0 +1.718281828459045 +-1 +2.6881171418161356e+43 +1.0000000005000001e-9 +-1 +Infinity +NaN +1.718281828459045 +1.718281828459045 +1.718281828459045 +1.718281828459045 +1.718281828459045 +111 +1.718281828459045 +1.718281828459045 +NaN +NaN +1.718281828459045 +6.38905609893065 +1.718281828459045 +6.38905609893065 +1.718281828459045 +1.718281828459045 +1.718281828459045 +NaN +obj.valueOf +-0.9999999998973812 +13.879731724872837 +NaN -- Gitee From 576e7da305f73ac67784cdccbecda373ab978435 Mon Sep 17 00:00:00 2001 From: Mikhail Kaskov Date: Wed, 13 Mar 2024 17:57:31 +0800 Subject: [PATCH 008/202] Implemented inlining of Math.Cbrt builtin * Added tests Change-Id: I678ee101b377c9b2d52e61a280913852fcd3477e Signed-off-by: Mikhail Kaskov --- ecmascript/builtins/builtins_math.h | 2 +- .../builtins/builtins_call_signature.h | 4 + ecmascript/compiler/call_signature.cpp | 1 + ecmascript/compiler/call_signature.h | 1 + ecmascript/compiler/mcr_opcodes.h | 1 + .../compiler/native_inline_lowering.cpp | 3 + .../compiler/number_speculative_retype.cpp | 1 + .../compiler/typed_native_inline_lowering.cpp | 3 + ecmascript/global_env_constants.h | 1 + ecmascript/stubs/runtime_stubs.cpp | 5 + ecmascript/stubs/runtime_stubs.h | 2 + test/aottest/builtin_inlining/math/BUILD.gn | 1 + .../builtin_inlining/math/Cbrt/BUILD.gn | 23 ++++ .../math/Cbrt/builtinMathCbrt.ts | 117 ++++++++++++++++++ .../math/Cbrt/expect_output.txt | 47 +++++++ .../math/Cbrt/pgo_expect_output.txt | 40 ++++++ 16 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 test/aottest/builtin_inlining/math/Cbrt/BUILD.gn create mode 100644 test/aottest/builtin_inlining/math/Cbrt/builtinMathCbrt.ts create mode 100644 test/aottest/builtin_inlining/math/Cbrt/expect_output.txt create mode 100644 test/aottest/builtin_inlining/math/Cbrt/pgo_expect_output.txt diff --git a/ecmascript/builtins/builtins_math.h b/ecmascript/builtins/builtins_math.h index 349451f89..1f3697f39 100644 --- a/ecmascript/builtins/builtins_math.h +++ b/ecmascript/builtins/builtins_math.h @@ -42,7 +42,7 @@ V("atan", Atan, 1, MathAtan) /* Math.atan ( x ) */ \ V("atan2", Atan2, 2, MathAtan2) /* Math.atan2 ( y, x ) */ \ V("atanh", Atanh, 1, MathAtanh) /* Math.atanh ( x ) */ \ - V("cbrt", Cbrt, 1, INVALID) /* Math.cbrt ( x ) */ \ + V("cbrt", Cbrt, 1, MathCbrt) /* Math.cbrt ( x ) */ \ V("ceil", Ceil, 1, INVALID) /* Math.ceil ( x ) */ \ V("clz32", Clz32, 1, INVALID) /* Math.clz32 ( x ) */ \ V("cos", Cos, 1, MathCos) /* Math.cos ( x ) */ \ diff --git a/ecmascript/compiler/builtins/builtins_call_signature.h b/ecmascript/compiler/builtins/builtins_call_signature.h index 96c5fe37b..0628491bd 100644 --- a/ecmascript/compiler/builtins/builtins_call_signature.h +++ b/ecmascript/compiler/builtins/builtins_call_signature.h @@ -147,6 +147,7 @@ namespace panda::ecmascript::kungfu { V(MathSin) \ V(MathSinh) \ V(MathTan) \ + V(MathCbrt) \ V(MathTanh) \ V(MathLog) \ V(MathLog2) \ @@ -313,6 +314,8 @@ public: return ConstantIndex::MATH_EXPM1_INDEX; case BuiltinsStubCSigns::ID::MathPow: return ConstantIndex::MATH_POW_INDEX; + case BuiltinsStubCSigns::ID::MathCbrt: + return ConstantIndex::MATH_CBRT_INDEX; case BuiltinsStubCSigns::ID::FLOOR: return ConstantIndex::MATH_FLOOR_FUNCTION_INDEX; case BuiltinsStubCSigns::ID::SQRT: @@ -366,6 +369,7 @@ public: {"Exp", MathExp}, {"Expm1", MathExpm1}, {"sqrt", SQRT}, + {"cbrt", MathCbrt}, {"abs", MathAbs}, {"pow", MathPow}, {"floor", FLOOR}, diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index 7710b4c4c..d6be3c948 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -1914,6 +1914,7 @@ DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatLog) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatLog2) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatLog10) DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatLog1p) +DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME(FloatCbrt) #undef DEF_FLOAT_UNARY_CALL_SIGNATURE_BY_NAME diff --git a/ecmascript/compiler/call_signature.h b/ecmascript/compiler/call_signature.h index 9fd134361..f0767d8af 100644 --- a/ecmascript/compiler/call_signature.h +++ b/ecmascript/compiler/call_signature.h @@ -461,6 +461,7 @@ private: V(FloatLog1p) \ V(FloatExp) \ V(FloatExpm1) \ + V(FloatCbrt) \ V(FloatFloor) \ V(FloatPow) \ V(FindElementWithCache) \ diff --git a/ecmascript/compiler/mcr_opcodes.h b/ecmascript/compiler/mcr_opcodes.h index 5c02e9a00..43bf84457 100644 --- a/ecmascript/compiler/mcr_opcodes.h +++ b/ecmascript/compiler/mcr_opcodes.h @@ -82,6 +82,7 @@ namespace panda::ecmascript::kungfu { V(MathExpm1, MATH_EXPM1, GateFlags::NO_WRITE, 1, 1, 1) \ V(MathAbs, MATH_ABS, GateFlags::NO_WRITE, 1, 1, 1) \ V(MathPow, MATH_POW, GateFlags::NO_WRITE, 1, 1, 2) \ + V(MathCbrt, MATH_CBRT, GateFlags::NO_WRITE, 1, 1, 1) \ MCR_BINARY_GATE_META_DATA_CACHE_LIST(V) #define MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \ diff --git a/ecmascript/compiler/native_inline_lowering.cpp b/ecmascript/compiler/native_inline_lowering.cpp index a1e60f10a..dd141f65a 100644 --- a/ecmascript/compiler/native_inline_lowering.cpp +++ b/ecmascript/compiler/native_inline_lowering.cpp @@ -125,6 +125,9 @@ void NativeInlineLowering::RunNativeInlineLowering() case BuiltinsStubCSigns::ID::MathPow: TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathPow()); break; + case BuiltinsStubCSigns::ID::MathCbrt: + TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCbrt()); + break; default: break; } diff --git a/ecmascript/compiler/number_speculative_retype.cpp b/ecmascript/compiler/number_speculative_retype.cpp index c65aa729c..6469fb63e 100644 --- a/ecmascript/compiler/number_speculative_retype.cpp +++ b/ecmascript/compiler/number_speculative_retype.cpp @@ -153,6 +153,7 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate) case OpCode::MATH_TAN: case OpCode::MATH_TANH: case OpCode::MATH_POW: + case OpCode::MATH_CBRT: return VisitMathBuiltin(gate); case OpCode::MATH_ABS: return VisitMathAbs(gate); diff --git a/ecmascript/compiler/typed_native_inline_lowering.cpp b/ecmascript/compiler/typed_native_inline_lowering.cpp index 28365996b..e0beb87da 100644 --- a/ecmascript/compiler/typed_native_inline_lowering.cpp +++ b/ecmascript/compiler/typed_native_inline_lowering.cpp @@ -84,6 +84,9 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate) case OpCode::MATH_POW: LowerMathPow(gate); break; + case OpCode::MATH_CBRT: + LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatCbrt)); + break; default: break; } diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index b637c4612..26401a2ac 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -173,6 +173,7 @@ class ObjectFactory; V(JSTaggedValue, MathExpm1, MATH_EXPM1_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathAbs, MATH_ABS_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathPow, MATH_POW_INDEX, ecma_roots_special) \ + V(JSTaggedValue, MathCbrt, MATH_CBRT_INDEX, ecma_roots_special) \ V(JSTaggedValue, MathFloorFunction, MATH_FLOOR_FUNCTION_INDEX, ecma_roots_special) \ V(JSTaggedValue, LocaleCompareFunction, LOCALE_COMPARE_FUNCTION_INDEX, ecma_roots_special) \ V(JSTaggedValue, ArraySortFunction, ARRAY_SORT_FUNCTION_INDEX, ecma_roots_special) \ diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 8ac959e64..7a43fa26d 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -2950,6 +2950,11 @@ double RuntimeStubs::FloatTanh(double x) return std::tanh(x); } +double RuntimeStubs::FloatCbrt(double x) +{ + return std::cbrt(x); +} + double RuntimeStubs::FloatFloor(double x) { ASSERT(!std::isnan(x)); diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 42e5d8bd1..d852695aa 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -136,6 +136,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co V(FloatLog1p) \ V(FloatExp) \ V(FloatExpm1) \ + V(FloatCbrt) \ V(FloatFloor) \ V(FloatPow) \ V(FindElementWithCache) \ @@ -498,6 +499,7 @@ public: static double FloatExp(double x); static double FloatExpm1(double x); static double FloatPow(double base, double exp); + static double FloatCbrt(double x); static int32_t FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass, JSTaggedType key, int32_t num); static bool StringsAreEquals(EcmaString *str1, EcmaString *str2); diff --git a/test/aottest/builtin_inlining/math/BUILD.gn b/test/aottest/builtin_inlining/math/BUILD.gn index c1120b86a..1aa83eaa7 100644 --- a/test/aottest/builtin_inlining/math/BUILD.gn +++ b/test/aottest/builtin_inlining/math/BUILD.gn @@ -35,6 +35,7 @@ group("ark_aot_builtin_inlining_math_test") { "Tanh", "Abs", "Pow", + "Cbrt", ] deps = [] diff --git a/test/aottest/builtin_inlining/math/Cbrt/BUILD.gn b/test/aottest/builtin_inlining/math/Cbrt/BUILD.gn new file mode 100644 index 000000000..c475819d0 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Cbrt/BUILD.gn @@ -0,0 +1,23 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_aot_test_action("builtinMathCbrt") { + is_enable_pgo = true + is_only_typed_path = true + is_enable_opt_inlining = true + is_enable_trace_deopt = true + log_option = " --log-info=trace" + deps = [] +} diff --git a/test/aottest/builtin_inlining/math/Cbrt/builtinMathCbrt.ts b/test/aottest/builtin_inlining/math/Cbrt/builtinMathCbrt.ts new file mode 100644 index 000000000..a8b3e0141 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Cbrt/builtinMathCbrt.ts @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function print(arg:any):string; +declare interface ArkTools { + isAOTCompiled(args: any): boolean; +} +function replace(a : number) +{ + return a; +} + +function doCbrt(x: any): number { + return Math.cbrt(x); +} + +function printCbrt(x: any) { + try { + print(doCbrt(x)); + } finally { + } +} + +let res:number = 1; + +// Check without params +print(Math.cbrt()); // NaN + +// Check with single param +print(Math.cbrt(-0.027)); // -0.3 +print(Math.cbrt(0.125)); // 0.5 +print(Math.cbrt(1)); // 1 +print(Math.cbrt(8)); // 2 +print(Math.cbrt(2146689000)); // 1290 +print(Math.cbrt(1_0000_0000_0000)); // 10000 +print(Math.cbrt(-1_0000_0000_0000)); // -10000 +print(Math.cbrt(10e80)); // 1e27 + +// Check with three param +print(Math.cbrt(64, 4, 6)); // 4 + +// If n is NaN, +0.0f or -0.0f, return n +res = Math.cbrt(+0.0); +print(res); // 0 +print("1/x: " + 1.0/res); // +inf + +res = Math.cbrt(-0.0); +print(res); // -0 +print("1/x: " + 1.0/res); // -inf + +print(Math.cbrt(NaN)); // NaN + +// Replace standard builtin +let true_cbrt = Math.cbrt; +Math.cbrt = replace; +print(Math.cbrt(0.001)); // 0.001, no deopt +Math.cbrt = true_cbrt; + +printCbrt("abcd"); // NaN +printCbrt("-125"); // -5 +printCbrt("abcdef"); // NaN + + +if (ArkTools.isAOTCompiled(printCbrt)) { + // Replace standard builtin after call to standard builtin was profiled + Math.cbrt = replace +} + +printCbrt(-216); // -6; or -216, deopt +printCbrt("abcd"); // NaN; or "abcd", deopt +Math.cbrt = true_cbrt; + +// Check IR correctness inside try-block +try { + printCbrt(10); // 2.1544346900318834 + printCbrt("abc"); // NaN +} catch (e) { +} + +let obj = {}; +obj.valueOf = (() => { return -64; }) +print(Math.cbrt(obj)); // -8 + +function Throwing() { + this.value = 100; +} + +Throwing.prototype.valueOf = function() { + if (this.value > 999) { + throw new Error("big value") + } + return this.value; +} + +let throwingObj = new Throwing(); + +try { + print(Math.cbrt(throwingObj)); // 4.641588834 + throwingObj.value = 1000; + print(Math.cbrt(throwingObj)); // exception +} catch(e) { + print(e); +} finally { + print(Math.cbrt(obj)); // -8 +} diff --git a/test/aottest/builtin_inlining/math/Cbrt/expect_output.txt b/test/aottest/builtin_inlining/math/Cbrt/expect_output.txt new file mode 100644 index 000000000..1529343cd --- /dev/null +++ b/test/aottest/builtin_inlining/math/Cbrt/expect_output.txt @@ -0,0 +1,47 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +NaN +-0.29999999999999992 +0.49999999999999992 +1 +2 +1290.0000000000002 +10000 +-10000 +1.0000000000000002e+27 +4 +0 +1/x: Infinity +0 +1/x: -Infinity +NaN +0.001 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotNumber1 +-5 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotCallTarget1 +-216 +[trace] Check Type: NotCallTarget1 +abcd +2.1544346900318834 +[trace] Check Type: NotNumber1 +NaN +[trace] Check Type: NotNumber1 +-4 +4.641588833612778 +Error: big value +-4 diff --git a/test/aottest/builtin_inlining/math/Cbrt/pgo_expect_output.txt b/test/aottest/builtin_inlining/math/Cbrt/pgo_expect_output.txt new file mode 100644 index 000000000..4f2988706 --- /dev/null +++ b/test/aottest/builtin_inlining/math/Cbrt/pgo_expect_output.txt @@ -0,0 +1,40 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +NaN +-0.29999999999999992 +0.49999999999999992 +1 +2 +1290.0000000000002 +10000 +-10000 +1.0000000000000002e+27 +4 +0 +1/x: Infinity +0 +1/x: -Infinity +NaN +0.001 +NaN +-5 +NaN +-6.000000000000001 +NaN +2.1544346900318834 +NaN +-4 +4.641588833612778 +Error: big value +-4 -- Gitee From 436e1ec5859ba1c843eb434e092da8d746c71b86 Mon Sep 17 00:00:00 2001 From: chenhantao Date: Wed, 20 Mar 2024 17:45:32 +0800 Subject: [PATCH 009/202] add typedarrayset test example Signed-off-by: chenhantao Change-Id: I0470c1fe47b85a50921f8ef3397a949ac5c50a7b --- test/moduletest/typedarrayset/BUILD.gn | 18 ++++++++++ .../typedarrayset/expect_output.txt | 21 ++++++++++++ .../moduletest/typedarrayset/typedarrayset.js | 34 +++++++++++++++++++ test/moduletest/typedarrayslice/BUILD.gn | 2 +- 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 test/moduletest/typedarrayset/BUILD.gn create mode 100644 test/moduletest/typedarrayset/expect_output.txt create mode 100644 test/moduletest/typedarrayset/typedarrayset.js diff --git a/test/moduletest/typedarrayset/BUILD.gn b/test/moduletest/typedarrayset/BUILD.gn new file mode 100644 index 000000000..05cafccad --- /dev/null +++ b/test/moduletest/typedarrayset/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/test/test_helper.gni") + +host_moduletest_action("typedarrayset") { + deps = [] +} diff --git a/test/moduletest/typedarrayset/expect_output.txt b/test/moduletest/typedarrayset/expect_output.txt new file mode 100644 index 000000000..580d4b68c --- /dev/null +++ b/test/moduletest/typedarrayset/expect_output.txt @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0 diff --git a/test/moduletest/typedarrayset/typedarrayset.js b/test/moduletest/typedarrayset/typedarrayset.js new file mode 100644 index 000000000..8d00f29da --- /dev/null +++ b/test/moduletest/typedarrayset/typedarrayset.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +[ + Float64Array, + Float32Array, + Int32Array, + Int16Array, + Int8Array, + Uint32Array, + Uint16Array, + Uint8Array, + Uint8ClampedArray +].forEach(function (ctor) { + testTypeArraySet1(ctor) +}); + +function testTypeArraySet1(ctor) { + const obj = new ctor(8); + obj.set(new ctor(6), 2); + print(obj); +} \ No newline at end of file diff --git a/test/moduletest/typedarrayslice/BUILD.gn b/test/moduletest/typedarrayslice/BUILD.gn index 2bca70f12..1fc4fb5d0 100644 --- a/test/moduletest/typedarrayslice/BUILD.gn +++ b/test/moduletest/typedarrayslice/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. +# Copyright (c) 2024 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -- Gitee From a5f1262b3c59d657e03970c758a32374efb8208b Mon Sep 17 00:00:00 2001 From: yanpeng Date: Mon, 18 Mar 2024 16:23:26 +0800 Subject: [PATCH 010/202] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=A8=E4=BE=8B?= =?UTF-8?q?=E6=95=B0=E6=B1=87=E6=80=BB=E5=92=8C=E5=8A=A3=E9=A1=B9=E5=80=BC?= =?UTF-8?q?=E6=B1=87=E6=80=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yanpeng Change-Id: Ib8368ddc3518bebf2882f9b040cf37e08c15f0e8 --- test/workloadtest/work_load.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/test/workloadtest/work_load.py b/test/workloadtest/work_load.py index db557f1d8..3273e6abc 100644 --- a/test/workloadtest/work_load.py +++ b/test/workloadtest/work_load.py @@ -131,7 +131,7 @@ def execute_shell_script(script_path, args): def configure_environment(path, file_path, tools_type): - text = "--case-path ts-swift-workload\n" \ + text = "--case-path weekly_workload\n" \ f"--ts-tools-path {path}\n" \ f"--tools-type {tools_type}\n" \ "--swift-tools-path ~/tools/swift-5.7.3-RELEASE-ubuntu22.04/usr/bin\n" \ @@ -172,14 +172,13 @@ def prepare_workload_code(path): def report(boundary_value: int): del_out_file() - folder_path = "./" - file_pattern = "pgo_data_*.xlsx" - file_paths = glob.glob(os.path.join(folder_path, file_pattern)) + file_paths = glob.glob(os.path.join("./", "pgo_data_*.xlsx")) red_fill = PatternFill(start_color='FF0000', end_color='FF0000', fill_type='solid') file_paths.sort(key=lambda x: datetime.datetime.strptime( x[WorkLoadConfig.START_INDEX:WorkLoadConfig.END_INDEX], "%Y%m%d%H%M%S"), reverse=True) max_two_files = file_paths[:2] + boundary_num = 0 if len(max_two_files) == 2: wb_one = load_workbook(max_two_files[0]) sheet_one = wb_one.active @@ -200,10 +199,11 @@ def report(boundary_value: int): case = row_one[0] average_one = row_one[-1] average_two = row_two[-1] - difference = (average_one - average_two) / average_one * 100 - percentage = "{:.2f}%".format(difference) - result_data.append([case, percentage]) - write_to_txt('../out/pgo_daily.txt', ''.join([case, percentage, '\n'])) + if average_one != 0: + difference = (average_one - average_two) / average_one * 100 + percentage = "{:.2f}%".format(difference) + result_data.append([case, percentage]) + write_to_txt('../out/pgo_daily.txt', ''.join([case, ":",percentage, '\n'])) result_wb = Workbook() result_sheet = result_wb.active result_sheet.append(['case', 'percentage']) @@ -212,12 +212,13 @@ def report(boundary_value: int): cell = result_sheet.cell(row=result_sheet.max_row, column=2) if cell.value and float(cell.value.strip('%')) < boundary_value: cell.fill = red_fill + boundary_num += 1 now = datetime.datetime.now() - formatted_date = now.strftime("%Y%m%d%H%M%S") - daily_excel_name = "".join(["pgo_daily_", formatted_date, ".xlsx"]) - daily_excel_out = "../out/pgo_daily.xlsx" - result_wb.save(daily_excel_name) - result_wb.save(daily_excel_out) + result_sheet.append(['Total_Case', str(len(result_data))]) + result_sheet.append(['Boundary_Total_Case', str(boundary_num)]) + write_to_txt('../out/pgo_daily.txt', ''.join(["Total_Case", ":", str(len(result_data)), '\n'])) + write_to_txt('../out/pgo_daily.txt', ''.join(["Boundary_Total_Case", ":", str(boundary_num), '\n'])) + result_wb.save(os.path.join("../out", "".join([now.strftime("%Y%m%d%H%M%S") + "_pgo_daily.xlsx"]))) def del_out_file(): @@ -254,6 +255,7 @@ def main(args): if code_v: execute_args.append('--code-v') execute_args.append(code_v) + execute_args.append('--run') execute_args.append('--run-count') execute_args.append(run_count) execute_shell_script("run_pgo.sh", execute_args) -- Gitee From a0185e8f50ef9e6074a7c62a664491a6035fcb68 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 9 Mar 2024 16:28:24 +0800 Subject: [PATCH 011/202] [cg] bugfix regalloc Signed-off-by: zhangyinlu Change-Id: Ibac27bb70fd86cb064ff490565165a569a0a5148 --- .../maple_be/include/cg/reg_alloc_lsra.h | 2 +- .../maple/maple_be/src/cg/reg_alloc_lsra.cpp | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h index b25bc1850..f86b9f11f 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/reg_alloc_lsra.h @@ -773,7 +773,7 @@ public: regno_t HandleSpillForLi(LiveInterval &li); MemOperand *GetSpillMem(uint32 vregNO, bool isDest, Insn &insn, regno_t regNO, bool &isOutOfRange, uint32 bitSize) const; - void InsertCallerSave(Insn &insn, Operand &opnd, bool isDef); + void InsertCallerSave(Insn &insn, Operand &opnd, bool isDef, uint32 spillIdx); uint32 GetRegFromMask(uint32 mask, regno_t offset, const LiveInterval &li); uint32 FindAvailablePhyReg(LiveInterval &li); uint32 AssignPhysRegs(LiveInterval &li); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp index 1c0a965f2..02bcebbd0 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/reg_alloc_lsra.cpp @@ -1359,7 +1359,7 @@ uint32 LSRALinearScanRegAllocator::FindAvailablePhyReg(LiveInterval &li) } /* Spill and reload for caller saved registers. */ -void LSRALinearScanRegAllocator::InsertCallerSave(Insn &insn, Operand &opnd, bool isDef) +void LSRALinearScanRegAllocator::InsertCallerSave(Insn &insn, Operand &opnd, bool isDef, uint32 spillIdx) { auto ®Opnd = static_cast(opnd); uint32 vRegNO = regOpnd.GetRegisterNumber(); @@ -1408,8 +1408,8 @@ void LSRALinearScanRegAllocator::InsertCallerSave(Insn &insn, Operand &opnd, boo bool isOutOfRange = false; if (isDef) { Insn *nextInsn = insn.GetNext(); - memOpnd = GetSpillMem(vRegNO, true, insn, static_cast(intSpillRegSet[0] + firstIntReg), isOutOfRange, - regSize); + memOpnd = GetSpillMem(vRegNO, true, insn, static_cast(intSpillRegSet[spillIdx + 1] + firstIntReg), + isOutOfRange, regSize); Insn *stInsn = regInfo->BuildStrInsn(regSize, spType, *phyOpnd, *memOpnd); comment = " SPILL for caller_save " + std::to_string(vRegNO); ++callerSaveSpillCount; @@ -1426,8 +1426,8 @@ void LSRALinearScanRegAllocator::InsertCallerSave(Insn &insn, Operand &opnd, boo insn.GetBB()->InsertInsnAfter(insn, *stInsn); } } else { - memOpnd = GetSpillMem(vRegNO, false, insn, static_cast(intSpillRegSet[0] + firstIntReg), isOutOfRange, - regSize); + memOpnd = GetSpillMem(vRegNO, false, insn, static_cast(intSpillRegSet[spillIdx] + firstIntReg), + isOutOfRange, regSize); Insn *ldInsn = regInfo->BuildLdrInsn(regSize, spType, *phyOpnd, *memOpnd); comment = " RELOAD for caller_save " + std::to_string(vRegNO); ++callerSaveReloadCount; @@ -1804,8 +1804,8 @@ RegOperand *LSRALinearScanRegAllocator::GetReplaceUdOpnd(Insn &insn, Operand &op } if (li->IsShouldSave()) { - InsertCallerSave(insn, opnd, false); - InsertCallerSave(insn, opnd, true); + InsertCallerSave(insn, opnd, false, spillIdx); + InsertCallerSave(insn, opnd, true, spillIdx); } else if (li->GetStackSlot() == kSpilled) { SpillOperand(insn, opnd, false, spillIdx); SpillOperand(insn, opnd, true, spillIdx); @@ -1846,11 +1846,13 @@ RegOperand *LSRALinearScanRegAllocator::GetReplaceOpnd(Insn &insn, Operand &opnd cgFunc->AddtoCalleeSaved(regNO); } - if (li->IsShouldSave()) { - InsertCallerSave(insn, opnd, isDef); - } else if (li->GetStackSlot() == kSpilled) { + if (li->IsShouldSave() || li->GetStackSlot() == kSpilled) { spillIdx = isDef ? 0 : spillIdx; - SpillOperand(insn, opnd, isDef, spillIdx); + if (li->IsShouldSave()) { + InsertCallerSave(insn, opnd, isDef, spillIdx); + } else { + SpillOperand(insn, opnd, isDef, spillIdx); + } if (!isDef) { ++spillIdx; } -- Gitee From b25ba052c4e674b1e42afbcb1f7850f85bf69f7c Mon Sep 17 00:00:00 2001 From: Artem Udovichenko Date: Thu, 7 Mar 2024 19:27:37 +0800 Subject: [PATCH 012/202] Implement hash calculation for number Change-Id: Ibf45fa2ad53197088a5f40a29513feedd92c5d04 Signed-off-by: Artem Udovichenko --- ecmascript/base/number_helper.cpp | 3 +- ecmascript/base/number_helper.h | 2 +- ecmascript/builtins/builtins.cpp | 2 +- .../linked_hashtable_stub_builder.cpp | 67 +++++++++--- .../builtins/linked_hashtable_stub_builder.h | 2 + ecmascript/compiler/circuit_builder.h | 2 + ecmascript/compiler/mcr_circuit_builder.cpp | 39 +++++++ ecmascript/compiler/stub_builder-inl.h | 6 ++ ecmascript/compiler/stub_builder.cpp | 101 ++++++++++++++++++ ecmascript/compiler/stub_builder.h | 5 + ecmascript/ecma_vm.cpp | 2 +- ecmascript/js_thread.h | 13 +++ 12 files changed, 224 insertions(+), 20 deletions(-) diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index 4c208fad0..f5a0f297a 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -1209,7 +1209,7 @@ uint64_t RandomGenerator::XorShift64(uint64_t *pVal) return x * GET_MULTIPLY; } -void RandomGenerator::InitRandom() +void RandomGenerator::InitRandom(JSThread *thread) { struct timeval tv; gettimeofday(&tv, NULL); @@ -1218,6 +1218,7 @@ void RandomGenerator::InitRandom() if (randomState_ == 0) { randomState_ = 1; } + thread->SetRandomStatePtr(&randomState_); } double RandomGenerator::NextDouble() diff --git a/ecmascript/base/number_helper.h b/ecmascript/base/number_helper.h index 00fccaa08..75db06695 100644 --- a/ecmascript/base/number_helper.h +++ b/ecmascript/base/number_helper.h @@ -171,7 +171,7 @@ private: // The value is used in xorshift64* random generator to generate result. class RandomGenerator { public: - static void InitRandom(); + static void InitRandom(JSThread *thread); static double NextDouble(); static int32_t GenerateIdentityHash(); static int32_t Next(int bits); diff --git a/ecmascript/builtins/builtins.cpp b/ecmascript/builtins/builtins.cpp index 02ae5ee1e..2713a51e3 100644 --- a/ecmascript/builtins/builtins.cpp +++ b/ecmascript/builtins/builtins.cpp @@ -1590,7 +1590,7 @@ void Builtins::InitializeMath(const JSHandle &env, const JSHandle mathClass = factory_->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, objFuncPrototypeVal); JSHandle mathObject = factory_->NewJSObjectWithInit(mathClass); - RandomGenerator::InitRandom(); + RandomGenerator::InitRandom(thread_); for (const base::BuiltinFunctionEntry &entry: Math::GetMathFunctions()) { SetFunction(env, mathObject, entry.GetName(), entry.GetEntrypoint(), diff --git a/ecmascript/compiler/builtins/linked_hashtable_stub_builder.cpp b/ecmascript/compiler/builtins/linked_hashtable_stub_builder.cpp index 7d2395549..3ce47883f 100644 --- a/ecmascript/compiler/builtins/linked_hashtable_stub_builder.cpp +++ b/ecmascript/compiler/builtins/linked_hashtable_stub_builder.cpp @@ -231,36 +231,70 @@ GateRef LinkedHashTableStubBuilder:: env->SubCfgEntry(&entryLabel); DEFVARIABLE(res, VariableType::INT32(), Int32(0)); + Label slowGetHash(env); Label symbolKey(env); Label stringCheck(env); BRANCH(TaggedIsSymbol(key), &symbolKey, &stringCheck); + Bind(&symbolKey); - { - res = Load(VariableType::INT32(), key, IntPtr(JSSymbol::HASHFIELD_OFFSET)); - Jump(&exit); - } + res = Load(VariableType::INT32(), key, IntPtr(JSSymbol::HASHFIELD_OFFSET)); + Jump(&exit); + Bind(&stringCheck); Label stringKey(env); - Label slowGetHash(env); - BRANCH(TaggedIsString(key), &stringKey, &slowGetHash); + Label objectCheck(env); + BRANCH(TaggedIsString(key), &stringKey, &objectCheck); Bind(&stringKey); - { - res = GetHashcodeFromString(glue_, key); - Jump(&exit); - } + res = GetHashcodeFromString(glue_, key); + Jump(&exit); + + Bind(&objectCheck); + Label heapObjectKey(env); + Label numberCheck(env); + BRANCH(TaggedIsHeapObject(key), &heapObjectKey, &numberCheck); + + Bind(&heapObjectKey); + Label ecmaObjectKey(env); + BRANCH(TaggedObjectIsEcmaObject(key), &ecmaObjectKey, &slowGetHash); + Bind(&ecmaObjectKey); + CalcHashcodeForObject(glue_, key, &res, &exit); + + Bind(&numberCheck); + Label numberKey(env); + BRANCH(TaggedIsNumber(key), &numberKey, &slowGetHash); + + Bind(&numberKey); + CalcHashcodeForNumber(key, &res, &exit); + Bind(&slowGetHash); - { - // GetHash(); - GateRef hash = CallRuntime(glue_, RTSTUB_ID(GetLinkedHash), { key }); - res = GetInt32OfTInt(hash); - Jump(&exit); - } + res = GetInt32OfTInt(CallRuntime(glue_, RTSTUB_ID(GetLinkedHash), { key })); + Jump(&exit); + Bind(&exit); auto ret = *res; env->SubCfgExit(); return ret; } +template +void LinkedHashTableStubBuilder::CalcHashcodeForNumber( + GateRef key, Variable *res, Label *exit) +{ + auto env = GetEnvironment(); + Label doubleKey(env); + Label intKey(env); + BRANCH(TaggedIsDouble(key), &doubleKey, &intKey); + Bind(&doubleKey); + { + CalcHashcodeForDouble(key, res, exit); + } + Bind(&intKey); + { + *res = CalcHashcodeForInt(key); + Jump(exit); + } +} + template GateRef LinkedHashTableStubBuilder::HashObjectIsMatch( GateRef key, GateRef other) @@ -624,6 +658,7 @@ GateRef LinkedHashTableStubBuilder:: BRANCH(Int32Equal(size, Int32(0)), &exit, &nonEmpty); Bind(&nonEmpty); GateRef hash = GetHash(key); + GateRef entry = FindElement(linkedTable, key, hash); Label findEntry(env); BRANCH(Int32Equal(entry, Int32(-1)), &exit, &findEntry); diff --git a/ecmascript/compiler/builtins/linked_hashtable_stub_builder.h b/ecmascript/compiler/builtins/linked_hashtable_stub_builder.h index 5481a0a69..14e6c3dc6 100644 --- a/ecmascript/compiler/builtins/linked_hashtable_stub_builder.h +++ b/ecmascript/compiler/builtins/linked_hashtable_stub_builder.h @@ -194,6 +194,8 @@ private: SetElement(linkedTable, bucketIndex, IntToTaggedInt(entry)); } + void CalcHashcodeForNumber(GateRef key, Variable *res, Label *exit); + GateRef GetDeletedElementsAt(GateRef linkedTable, GateRef entry); GateRef GrowCapacity(GateRef linkedTable, GateRef numberOfAddedElements); GateRef HasSufficientCapacity(GateRef linkedTable, GateRef numOfAddElements); diff --git a/ecmascript/compiler/circuit_builder.h b/ecmascript/compiler/circuit_builder.h index 94377cf46..9bd53690e 100644 --- a/ecmascript/compiler/circuit_builder.h +++ b/ecmascript/compiler/circuit_builder.h @@ -699,6 +699,8 @@ public: GateRef NumberToString(GateRef number); GateRef TaggedPointerToInt64(GateRef x); GateRef GetLengthFromString(GateRef value); + GateRef Rotl(GateRef word, uint32_t shift); + GateRef CalcHashcodeForInt(GateRef value); GateRef GetHashcodeFromString(GateRef glue, GateRef value); GateRef TryGetHashcodeFromString(GateRef string); GateRef IsIntegerString(GateRef string); diff --git a/ecmascript/compiler/mcr_circuit_builder.cpp b/ecmascript/compiler/mcr_circuit_builder.cpp index 940f75a29..3bb960eb6 100644 --- a/ecmascript/compiler/mcr_circuit_builder.cpp +++ b/ecmascript/compiler/mcr_circuit_builder.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include "libpandabase/utils/hash.h" + #include "ecmascript/compiler/mcr_circuit_builder.h" #include "ecmascript/message_string.h" #include "ecmascript/stubs/runtime_stubs-inl.h" @@ -1161,6 +1163,43 @@ GateRef CircuitBuilder::GetLengthFromString(GateRef value) return Int32LSR(len, Int32(EcmaString::STRING_LENGTH_SHIFT_COUNT)); } +GateRef CircuitBuilder::Rotl(GateRef word, uint32_t shift) +{ + static constexpr uint32_t MAX_BITS = 32; + return Int32Or(Int32LSL(word, Int32(shift)), Int32LSR(word, Int32(MAX_BITS - shift))); +} + +GateRef CircuitBuilder::CalcHashcodeForInt(GateRef value) +{ + GateRef rawVal = ChangeTaggedPointerToInt64(value); + GateRef low = TruncInt64ToInt32(rawVal); + GateRef k1 = Int32Mul(low, Int32(MurmurHash32Const::C1)); + GateRef k2 = Rotl(k1, MurmurHash32Const::MAIN_FIRST_SHIFT); + GateRef k3 = Int32Mul(k2, Int32(MurmurHash32Const::C2)); + GateRef hash1 = Int32Xor(Int32(DEFAULT_SEED), k3); + GateRef hash2 = Rotl(hash1, MurmurHash32Const::MAIN_SECOND_SHIFT); + GateRef hash3 = Int32Add(Int32Mul(hash2, Int32(MurmurHash32Const::MAIN_MULTIPLICATOR)), + Int32(MurmurHash32Const::MAIN_CONSTANT)); + + GateRef high = TruncInt64ToInt32(Int64LSR(rawVal, Int64(32U))); + GateRef k4 = Int32Mul(high, Int32(MurmurHash32Const::C1)); + GateRef k5 = Rotl(k4, MurmurHash32Const::MAIN_FIRST_SHIFT); + GateRef k6 = Int32Mul(k5, Int32(MurmurHash32Const::C2)); + GateRef hash4 = Int32Xor(hash3, k6); + GateRef hash5 = Rotl(hash4, MurmurHash32Const::MAIN_SECOND_SHIFT); + GateRef hash6 = Int32Add(Int32Mul(hash5, Int32(MurmurHash32Const::MAIN_MULTIPLICATOR)), + Int32(MurmurHash32Const::MAIN_CONSTANT)); + + GateRef hash7 = Int32Xor(hash6, Int32(8U)); + // Finalize + GateRef hash8 = Int32Xor(hash7, Int32LSR(hash7, Int32(MurmurHash32Const::FINALIZE_FIRST_SHIFT))); + GateRef hash9 = Int32Mul(hash8, Int32(MurmurHash32Const::FINALIZE_FIRST_MULTIPLICATOR)); + GateRef hash10 = Int32Xor(hash9, Int32LSR(hash9, Int32(MurmurHash32Const::FINALIZE_SECOND_SHIFT))); + GateRef hash11 = Int32Mul(hash10, Int32(MurmurHash32Const::FINALIZE_SECOND_MULTIPLICATOR)); + GateRef hash12 = Int32Xor(hash11, Int32LSR(hash11, Int32(MurmurHash32Const::FINALIZE_THIRD_SHIFT))); + return hash12; +} + GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value) { ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame()); diff --git a/ecmascript/compiler/stub_builder-inl.h b/ecmascript/compiler/stub_builder-inl.h index 2a150704e..83b012092 100644 --- a/ecmascript/compiler/stub_builder-inl.h +++ b/ecmascript/compiler/stub_builder-inl.h @@ -1064,6 +1064,12 @@ inline void StubBuilder::SetPropertiesArray(VariableType type, GateRef glue, Gat Store(type, glue, object, propertiesOffset, propsArray); } +inline GateRef StubBuilder::GetHash(GateRef object) +{ + GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); + return Load(VariableType::JS_ANY(), object, hashOffset); +} + inline void StubBuilder::SetHash(GateRef glue, GateRef object, GateRef hash) { GateRef hashOffset = IntPtr(ECMAObject::HASH_OFFSET); diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index 0fe3631c7..08c2476f0 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -6684,6 +6684,107 @@ void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue) return; } +GateRef StubBuilder::CalcHashcodeForInt(GateRef value) +{ + return env_->GetBuilder()->CalcHashcodeForInt(value); +} + +GateRef StubBuilder::CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits) +{ + GateRef isNanOrInf = Int64Equal(expBits, Int64(base::DOUBLE_EXPONENT_MASK)); + GateRef isSubnormal = BoolAnd( + Int64Equal(expBits, Int64(0)), + Int64NotEqual(fractionBits, Int64(0))); + GateRef hasFraction = Int64NotEqual( + Int64And( + Int64LSL(fractionBits, exp), + Int64(base::DOUBLE_SIGNIFICAND_MASK)), + Int64(0)); + GateRef badExp = BoolOr( + Int64LessThan(exp, Int64(0)), + Int64GreaterThanOrEqual(exp, Int64(31U))); + return BoolOr(BoolOr(BoolOr(isNanOrInf, isSubnormal), badExp), hasFraction); +} + +void StubBuilder::CalcHashcodeForDouble(GateRef x, Variable *res, Label *exit) +{ + auto env = GetEnvironment(); + GateRef xInt64 = ChangeTaggedPointerToInt64(x); + GateRef fractionBits = Int64And(xInt64, Int64(base::DOUBLE_SIGNIFICAND_MASK)); + GateRef expBits = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK)); + GateRef signBit = Int64And(xInt64, Int64(base::DOUBLE_SIGN_MASK)); + GateRef isZero = BoolAnd( + Int64Equal(expBits, Int64(0)), + Int64Equal(fractionBits, Int64(0))); + Label zero(env); + Label nonZero(env); + + BRANCH(isZero, &zero, &nonZero); + Bind(&nonZero); + { + DEFVARIABLE(value, VariableType::JS_ANY(), x); + // exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS + GateRef exp = Int64Sub( + Int64LSR(expBits, Int64(base::DOUBLE_SIGNIFICAND_SIZE)), + Int64(base::DOUBLE_EXPONENT_BIAS)); + Label convertToInt(env); + Label calcHash(env); + BRANCH(CanDoubleRepresentInt(exp, expBits, fractionBits), &calcHash, &convertToInt); + Bind(&convertToInt); + { + GateRef shift = Int64Sub(Int64(base::DOUBLE_SIGNIFICAND_SIZE), exp); + GateRef intVal = Int64Add( + Int64LSL(Int64(1), exp), + Int64LSR(fractionBits, shift)); + DEFVARIABLE(intVariable, VariableType::INT64(), intVal); + Label negate(env); + Label pass(env); + BRANCH(Int64NotEqual(signBit, Int64(0)), &negate, &calcHash); + Bind(&negate); + { + intVariable = Int64Sub(Int64(0), intVal); + Jump(&pass); + } + Bind(&pass); + value = Int64ToTaggedPtr(*intVariable); + Jump(&calcHash); + } + Bind(&calcHash); + { + *res = env_->GetBuilder()->CalcHashcodeForInt(*value); + Jump(exit); + } + } + + Bind(&zero); + *res = env_->GetBuilder()->CalcHashcodeForInt(IntToTaggedPtr(Int32(0))); + Jump(exit); +} + +void StubBuilder::CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit) +{ + auto env = GetEnvironment(); + + GateRef hash = GetHash(value); + *res = TruncInt64ToInt32(TaggedCastToIntPtr(hash)); + Label calcHash(env); + BRANCH(Int32Equal(**res, Int32(0)), &calcHash, exit); + Bind(&calcHash); + GateRef offset = IntPtr(JSThread::GlueData::GetRandomStatePtrOffset(env_->Is32Bit())); + GateRef randomStatePtr = Load(VariableType::NATIVE_POINTER(), glue, offset); + GateRef randomState = Load(VariableType::INT64(), randomStatePtr, IntPtr(0)); + GateRef k1 = Int64Xor(randomState, Int64LSR(randomState, Int64(base::RIGHT12))); + GateRef k2 = Int64Xor(k1, Int64LSL(k1, Int64(base::LEFT25))); + GateRef k3 = Int64Xor(k2, Int64LSR(k2, Int64(base::RIGHT27))); + Store(VariableType::INT64(), glue, randomStatePtr, IntPtr(0), k3); + GateRef k4 = Int64Mul(k3, Int64(base::GET_MULTIPLY)); + GateRef k5 = Int64LSR(k4, Int64(base::INT64_BITS - base::INT32_BITS)); + GateRef k6 = Int32And(TruncInt64ToInt32(k5), Int32(INT32_MAX)); + SetHash(glue, value, IntToTaggedPtr(k6)); + *res = k6; + Jump(exit); +} + GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value) { return env_->GetBuilder()->GetHashcodeFromString(glue, value); diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 2cbe2451d..eac15a183 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -321,6 +321,7 @@ public: GateRef GetPropertiesArray(GateRef object); // SetProperties in js_object.h void SetPropertiesArray(VariableType type, GateRef glue, GateRef object, GateRef propsArray); + GateRef GetHash(GateRef object); void SetHash(GateRef glue, GateRef object, GateRef hash); GateRef GetLengthOfTaggedArray(GateRef array); GateRef GetLengthOfJSTypedArray(GateRef array); @@ -450,6 +451,9 @@ public: GateRef GetLayoutFromHClass(GateRef hClass); GateRef GetBitFieldFromHClass(GateRef hClass); GateRef GetLengthFromString(GateRef value); + GateRef CalcHashcodeForInt(GateRef value); + void CalcHashcodeForDouble(GateRef value, Variable *res, Label *exit); + void CalcHashcodeForObject(GateRef glue, GateRef value, Variable *res, Label *exit); GateRef GetHashcodeFromString(GateRef glue, GateRef value); inline GateRef IsIntegerString(GateRef string); inline void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode, GateRef isInteger); @@ -856,6 +860,7 @@ private: void InitializeArguments(); void CheckDetectorName(GateRef glue, GateRef key, Label *fallthrough, Label *slow); bool IsCallModeSupportPGO(JSCallMode mode); + GateRef CanDoubleRepresentInt(GateRef exp, GateRef expBits, GateRef fractionBits); CallSignature *callSignature_ {nullptr}; Environment *env_; diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index f5ee33824..54e800126 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -150,7 +150,7 @@ void EcmaVM::PreFork() void EcmaVM::PostFork() { - RandomGenerator::InitRandom(); + RandomGenerator::InitRandom(GetAssociatedJSThread()); heap_->SetHeapMode(HeapMode::SHARE); GetAssociatedJSThread()->PostFork(); Taskpool::GetCurrentTaskpool()->Initialize(); diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index 0955bfd7b..ab5fb291a 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -814,6 +814,11 @@ public: return glueData_.propertiesGrowStep_; } + void SetRandomStatePtr(uint64_t *ptr) + { + glueData_.randomStatePtr_ = reinterpret_cast(ptr); + } + struct GlueData : public base::AlignedStruct { enum class Index : size_t { BCStubEntriesIndex = 0, @@ -879,6 +885,7 @@ public: BuiltinEntriesIndex, IsTracingIndex, unsharedConstpoolsIndex, + RandomStatePtrIndex, stateAndFlagsIndex, NumOfMembers }; @@ -1054,6 +1061,11 @@ public: return GetOffset(Index::stateAndFlagsIndex)>(isArch32); } + static size_t GetRandomStatePtrOffset(bool isArch32) + { + return GetOffset(Index::RandomStatePtrIndex)>(isArch32); + } + alignas(EAS) BCStubEntries bcStubEntries_; alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()}; alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()}; @@ -1085,6 +1097,7 @@ public: alignas(EAS) BuiltinEntries builtinEntries_; alignas(EAS) bool isTracing_ {false}; alignas(EAS) uintptr_t unsharedConstpools_ {0}; + alignas(EAS) uintptr_t randomStatePtr_ {0}; alignas(EAS) ThreadStateAndFlags stateAndFlags_ {}; }; STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64); -- Gitee From 94791abd90a0ed5adb0de9314d673eab41d7e0cd Mon Sep 17 00:00:00 2001 From: xiaoweidong Date: Thu, 21 Mar 2024 21:32:14 +0800 Subject: [PATCH 013/202] [JIT] Add jit option in napi for app enable test 1. now just add option for app, not enable default Change-Id: I70d9edca6086b95528b20efd47ce914d7b766fd1 Signed-off-by: xiaoweidong --- ecmascript/compiler/jit_compiler.cpp | 22 +++++++++------------- ecmascript/compiler/jit_compiler.h | 10 +++++----- ecmascript/ecma_vm.cpp | 10 +++++----- ecmascript/jit/jit.cpp | 17 +++++++++++++---- ecmascript/jit/jit.h | 4 ++-- ecmascript/js_runtime_options.h | 11 +++++++++++ ecmascript/napi/include/jsnapi.h | 11 +++++++++++ ecmascript/napi/jsnapi_expo.cpp | 5 ++++- ecmascript/runtime.cpp | 3 +++ 9 files changed, 63 insertions(+), 30 deletions(-) diff --git a/ecmascript/compiler/jit_compiler.cpp b/ecmascript/compiler/jit_compiler.cpp index ca56ede8d..c618f0629 100644 --- a/ecmascript/compiler/jit_compiler.cpp +++ b/ecmascript/compiler/jit_compiler.cpp @@ -25,15 +25,14 @@ #include "ecmascript/platform/file.h" namespace panda::ecmascript::kungfu { -JitCompiler *JitCompiler::GetInstance(EcmaVM *vm) +JitCompiler *JitCompiler::GetInstance(JSRuntimeOptions *options) { - static JitCompiler instance(vm); + static JitCompiler instance(options); return &instance; } -JitCompilationOptions::JitCompilationOptions(EcmaVM *vm) +JitCompilationOptions::JitCompilationOptions(JSRuntimeOptions runtimeOptions) { - JSRuntimeOptions &runtimeOptions = vm->GetJSOptions(); #if defined(PANDA_TARGET_AMD64) triple_ = TARGET_X64; #elif defined(PANDA_TARGET_ARM64) @@ -57,7 +56,7 @@ JitCompilationOptions::JitCompilationOptions(EcmaVM *vm) isEnableOptInlining_ = runtimeOptions.IsEnableOptInlining(); isEnableOptString_ = runtimeOptions.IsEnableOptString(); isEnableTypeInfer_ = - isEnableTypeLowering_ || vm->GetJSThread()->GetCurrentEcmaContext()->GetTSManager()->AssertTypes(); + isEnableTypeLowering_ || runtimeOptions.AssertTypes(); isEnableOptPGOType_ = runtimeOptions.IsEnableOptPGOType(); isEnableOptTrackField_ = runtimeOptions.IsEnableOptTrackField(); isEnableOptLoopPeeling_ = runtimeOptions.IsEnableOptLoopPeeling(); @@ -70,13 +69,13 @@ JitCompilationOptions::JitCompilationOptions(EcmaVM *vm) isEnableLoweringBuiltin_ = runtimeOptions.IsEnableLoweringBuiltin(); } -void JitCompiler::Init(EcmaVM *vm) +void JitCompiler::Init(JSRuntimeOptions runtimeOptions) { BytecodeStubCSigns::Initialize(); CommonStubCSigns::Initialize(); RuntimeStubCSigns::Initialize(); - JitCompilationOptions jitOptions(vm); + JitCompilationOptions jitOptions(runtimeOptions); jitOptions_ = jitOptions; PassOptions::Builder optionsBuilder; passOptions_ = @@ -148,13 +147,10 @@ bool JitCompilerTask::Finalize(JitTask *jitTask) return true; } -void InitJitCompiler(EcmaVM *vm) +void InitJitCompiler(JSRuntimeOptions options) { - if (vm == nullptr) { - return; - } - JitCompiler *jitCompiler = JitCompiler::GetInstance(vm); - jitCompiler->Init(vm); + JitCompiler *jitCompiler = JitCompiler::GetInstance(&options); + jitCompiler->Init(options); } void *CreateJitCompilerTask(JitTask *jitTask) diff --git a/ecmascript/compiler/jit_compiler.h b/ecmascript/compiler/jit_compiler.h index 31948eaea..fcf92252b 100644 --- a/ecmascript/compiler/jit_compiler.h +++ b/ecmascript/compiler/jit_compiler.h @@ -22,7 +22,7 @@ namespace panda::ecmascript::kungfu { extern "C" { -PUBLIC_API void InitJitCompiler(EcmaVM *vm); +PUBLIC_API void InitJitCompiler(JSRuntimeOptions options); PUBLIC_API void *CreateJitCompilerTask(JitTask *jitTask); PUBLIC_API bool JitCompile(void *compiler, JitTask *jitTask); PUBLIC_API bool JitFinalize(void *compiler, JitTask *jitTask); @@ -30,7 +30,7 @@ PUBLIC_API void DeleteJitCompile(void *handle); }; struct JitCompilationOptions { - JitCompilationOptions(EcmaVM *vm); + JitCompilationOptions(JSRuntimeOptions options); JitCompilationOptions() = default; std::string triple_; @@ -84,14 +84,14 @@ private: class JitCompiler final { public: - explicit JitCompiler(EcmaVM *vm) : jitOptions_(vm), + explicit JitCompiler(JSRuntimeOptions *options) : jitOptions_(*options), log_(jitOptions_.logOption_), logList_(jitOptions_.logMethodsList_), profilerDecoder_(jitOptions_.profilerIn_, jitOptions_.hotnessThreshold_) { } ~JitCompiler() = default; - void Init(EcmaVM *vm); + void Init(JSRuntimeOptions options); - static JitCompiler *GetInstance(EcmaVM *vm = nullptr); + static JitCompiler *GetInstance(JSRuntimeOptions *options = nullptr); JitCompilationOptions &GetJitOptions() { return jitOptions_; diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index f5ee33824..aff2ebf03 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -164,6 +164,10 @@ void EcmaVM::PostFork() options_.SetEnablePGOProfiler(true); } ResetPGOProfiler(); + + bool isEnableJit = options_.IsEnableJIT() && options_.GetEnableAsmInterpreter(); + options_.SetEnableAPPJIT(true); + Jit::GetInstance()->SetEnableOrDisable(options_, isEnableJit); #ifdef ENABLE_POSTFORK_FORCEEXPAND heap_->NotifyPostFork(); heap_->NotifyFinishColdStartSoon(); @@ -219,15 +223,11 @@ bool EcmaVM::IsEnableElementsKind() const bool EcmaVM::IsEnableJit() const { - if (options_.IsWorker()) { - return GetJit()->IsEnable(); - } - return options_.GetEnableAsmInterpreter() && options_.IsEnableJIT(); + return GetJit()->IsEnable(); } void EcmaVM::EnableJit() const { - Jit::GetInstance()->SetEnable(this); GetJSThread()->SwitchJitProfileStubs(); } diff --git a/ecmascript/jit/jit.cpp b/ecmascript/jit/jit.cpp index 6e9b86af9..615c8cc5a 100644 --- a/ecmascript/jit/jit.cpp +++ b/ecmascript/jit/jit.cpp @@ -21,7 +21,7 @@ namespace panda::ecmascript { std::deque Jit::asyncCompileJitTasks_; Mutex Jit::asyncCompileJitTasksMtx_; -void (*Jit::initJitCompiler_)(EcmaVM *vm) = nullptr; +void (*Jit::initJitCompiler_)(JSRuntimeOptions options) = nullptr; bool(*Jit::jitCompile_)(void*, JitTask*) = nullptr; bool(*Jit::jitFinalize_)(void*, JitTask*) = nullptr; void*(*Jit::createJitCompilerTask_)(JitTask*) = nullptr; @@ -34,14 +34,23 @@ Jit *Jit::GetInstance() return &instance_; } -void Jit::SetEnable(const EcmaVM *vm) +void Jit::SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnable) { + if (options.IsEnableAPPJIT()) { + // temporary for app jit options test. + LOG_JIT(DEBUG) << (isEnable ? "jit is enable" : "jit is disable"); + return; + } + if (!isEnable) { + jitEnable_ = false; + return; + } if (!initialized_) { Initialize(); } if (initialized_ && !jitEnable_) { jitEnable_ = true; - initJitCompiler_(const_cast(vm)); + initJitCompiler_(options); } } @@ -65,7 +74,7 @@ void Jit::Initialize() return; } - initJitCompiler_ = reinterpret_cast(FindSymbol(libHandle_, JITCOMPILEINIT.c_str())); + initJitCompiler_ = reinterpret_cast(FindSymbol(libHandle_, JITCOMPILEINIT.c_str())); if (initJitCompiler_ == nullptr) { LOG_JIT(ERROR) << "jit can't find symbol initJitCompiler"; return; diff --git a/ecmascript/jit/jit.h b/ecmascript/jit/jit.h index d12608206..154737bd6 100644 --- a/ecmascript/jit/jit.h +++ b/ecmascript/jit/jit.h @@ -33,7 +33,7 @@ public: Jit() {} ~Jit(); static Jit *GetInstance(); - void SetEnable(const EcmaVM *vm); + void SetEnableOrDisable(const JSRuntimeOptions &options, bool isEnable); bool IsEnable(); void Initialize(); @@ -76,7 +76,7 @@ private: Mutex installJitTasksDequeMtx_; static Mutex asyncCompileJitTasksMtx_; - static void (*initJitCompiler_)(EcmaVM *vm); + static void (*initJitCompiler_)(JSRuntimeOptions); static bool(*jitCompile_)(void*, JitTask*); static bool(*jitFinalize_)(void*, JitTask*); static void*(*createJitCompilerTask_)(JitTask*); diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 4272ff903..f2a1a5d73 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -1077,6 +1077,16 @@ public: return enableJIT_; } + void SetEnableAPPJIT(bool value) + { + enableAPPJIT_ = value; + } + + bool IsEnableAPPJIT() const + { + return enableAPPJIT_; + } + void SetJitHotnessThreshold(uint16_t value) { jitHotnessThreshold_ = value; @@ -1618,6 +1628,7 @@ private: bool enableOptInlining_ {true}; bool enableOptPGOType_ {true}; bool enableJIT_{false}; + bool enableAPPJIT_{false}; uint16_t jitHotnessThreshold_ {2}; bool forceJitCompileMain_{false}; bool enableGlobalTypeInfer_ {false}; diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index ed926d685..b993a0002 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -366,6 +366,16 @@ private: return profileDir_; } + void SetEnableJIT(bool value) + { + enableJIT_ = value; + } + + bool GetEnableJIT() const + { + return enableJIT_; + } + GC_TYPE gcType_ = GC_TYPE::EPSILON; LOG_LEVEL logLevel_ = LOG_LEVEL::DEBUG; uint32_t gcPoolSize_ = ecmascript::DEFAULT_GC_POOL_SIZE; @@ -386,6 +396,7 @@ private: std::string anDir_ {}; bool enableProfile_ {false}; std::string profileDir_ {}; + bool enableJIT_ {false}; friend JSNApi; }; diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index bfdad4675..f1d537e83 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -103,6 +103,7 @@ #include "ecmascript/platform/mutex.h" #include "ecmascript/platform/log.h" +#include "ecmascript/jit/jit.h" namespace panda { using ecmascript::AccessorData; @@ -3181,7 +3182,8 @@ EcmaVM *JSNApi::CreateJSVM(const RuntimeOption &option) runtimeOptions.SetEnableAOT(option.GetEnableAOT()); runtimeOptions.SetEnablePGOProfiler(option.GetEnableProfile()); runtimeOptions.SetPGOProfilerPath(option.GetProfileDir()); - + // jit + runtimeOptions.SetEnableJIT(option.GetEnableJIT()); // Dfx runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel()))); runtimeOptions.SetEnableArkTools(option.GetEnableArkTools()); @@ -3826,6 +3828,7 @@ void JSNApi::PostFork(EcmaVM *vm, const RuntimeOption &option) << ", aot: " << jsOption.GetEnableAOT() << ", bundle name: " << option.GetBundleName(); jsOption.SetEnablePGOProfiler(option.GetEnableProfile()); + jsOption.SetEnableJIT(option.GetEnableJIT()); ecmascript::pgo::PGOProfilerManager::GetInstance()->SetBundleName(option.GetBundleName()); JSRuntimeOptions runtimeOptions; runtimeOptions.SetLogLevel(Log::LevelToString(Log::ConvertFromRuntime(option.GetLogLevel()))); diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index 6d5140e7f..3bdbd56ce 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -18,6 +18,7 @@ #include "ecmascript/compiler/aot_file/an_file_data_manager.h" #include "ecmascript/ecma_vm.h" +#include "ecmascript/jit/jit.h" #include "ecmascript/ecma_string_table.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/mem/mem_map_allocator.h" @@ -49,6 +50,8 @@ void Runtime::CreateIfFirstVm(const JSRuntimeOptions &options) MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE); PGOProfilerManager::GetInstance()->Initialize(options.GetPGOProfilerPath(), options.GetPGOHotnessThreshold()); + bool isEnableJit = options.IsEnableJIT() && options.GetEnableAsmInterpreter(); + Jit::GetInstance()->SetEnableOrDisable(options, isEnableJit); ASSERT(instance_ == nullptr); instance_ = new Runtime(); firstVmCreated_ = true; -- Gitee From f03cdddbe6fec93aa5f3684b5e4afd53d8574865 Mon Sep 17 00:00:00 2001 From: Gymee Date: Wed, 21 Feb 2024 11:52:04 +0800 Subject: [PATCH 014/202] Make linked hash table can be shared allocated Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I93TZC Signed-off-by: Gymee Change-Id: I0bcb1677341bd1a4e2d97b6d9b54b7a4e688bc46 --- ecmascript/linked_hash_table.cpp | 31 ++++++++++++++++++++----------- ecmascript/linked_hash_table.h | 8 +++++--- ecmascript/mem/space.h | 5 +++++ ecmascript/tagged_dictionary.cpp | 2 +- ecmascript/tagged_hash_table.h | 12 +++++++----- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/ecmascript/linked_hash_table.cpp b/ecmascript/linked_hash_table.cpp index 1dc23868e..de668f956 100644 --- a/ecmascript/linked_hash_table.cpp +++ b/ecmascript/linked_hash_table.cpp @@ -20,15 +20,20 @@ namespace panda::ecmascript { template -JSHandle LinkedHashTable::Create(const JSThread *thread, int numberOfElements) +JSHandle LinkedHashTable::Create(const JSThread *thread, + int numberOfElements, MemSpaceKind spaceKind) { ASSERT_PRINT(numberOfElements > 0, "size must be a non-negative integer"); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); auto capacity = static_cast(numberOfElements); ASSERT_PRINT(helpers::math::IsPowerOfTwo(capacity), "capacity must be pow of '2'"); int length = ELEMENTS_START_INDEX + numberOfElements + numberOfElements * (HashObject::ENTRY_SIZE + 1); - - auto table = JSHandle(factory->NewTaggedArray(length)); + JSHandle table; + if (spaceKind == MemSpaceKind::SHARED) { + table = JSHandle(factory->NewSOldSpaceTaggedArray(length)); + } else { + table = JSHandle(factory->NewTaggedArray(length)); + } table->SetNumberOfElements(thread, 0); table->SetNumberOfDeletedElements(thread, 0); table->SetCapacity(thread, capacity); @@ -96,7 +101,8 @@ JSHandle LinkedHashTable::GrowCapacity(const JSThr return table; } int newCapacity = ComputeCapacity(table->NumberOfElements() + numberOfAddedElements); - JSHandle newTable = Create(thread, newCapacity); + JSHandle newTable = Create(thread, newCapacity, + table.GetTaggedValue().IsInSharedHeap() ? MemSpaceKind::SHARED : MemSpaceKind::LOCAL); table->Rehash(thread, *newTable); return newTable; } @@ -123,16 +129,17 @@ JSHandle LinkedHashTable::Shrink(const JSThread *t return table; } - JSHandle newTable = Create(thread, newCapacity); + JSHandle newTable = Create(thread, newCapacity, + table.GetTaggedValue().IsInSharedHeap() ? MemSpaceKind::SHARED : MemSpaceKind::LOCAL); table->Rehash(thread, *newTable); return newTable; } // LinkedHashMap -JSHandle LinkedHashMap::Create(const JSThread *thread, int numberOfElements) +JSHandle LinkedHashMap::Create(const JSThread *thread, int numberOfElements, MemSpaceKind spaceKind) { - return LinkedHashTable::Create(thread, numberOfElements); + return LinkedHashTable::Create(thread, numberOfElements, spaceKind); } JSHandle LinkedHashMap::Delete(const JSThread *thread, const JSHandle &obj, @@ -170,7 +177,8 @@ bool LinkedHashMap::Has(const JSThread *thread, JSTaggedValue key) const JSHandle LinkedHashMap::Clear(const JSThread *thread, const JSHandle &table) { - JSHandle newMap = LinkedHashMap::Create(thread); + JSHandle newMap = LinkedHashMap::Create(thread, LinkedHashMap::MIN_CAPACITY, + table.GetTaggedValue().IsInSharedHeap() ? MemSpaceKind::SHARED : MemSpaceKind::LOCAL); if (table->Capacity() > 0) { table->SetNextTable(thread, newMap.GetTaggedValue()); table->SetNumberOfDeletedElements(thread, -1); @@ -185,9 +193,9 @@ JSHandle LinkedHashMap::Shrink(const JSThread *thread, const JSHa } // LinkedHashSet -JSHandle LinkedHashSet::Create(const JSThread *thread, int numberOfElements) +JSHandle LinkedHashSet::Create(const JSThread *thread, int numberOfElements, MemSpaceKind spaceKind) { - return LinkedHashTable::Create(thread, numberOfElements); + return LinkedHashTable::Create(thread, numberOfElements, spaceKind); } JSHandle LinkedHashSet::Delete(const JSThread *thread, const JSHandle &obj, @@ -216,7 +224,8 @@ bool LinkedHashSet::Has(const JSThread *thread, JSTaggedValue key) const JSHandle LinkedHashSet::Clear(const JSThread *thread, const JSHandle &table) { - JSHandle newSet = LinkedHashSet::Create(thread); + JSHandle newSet = LinkedHashSet::Create(thread, LinkedHashSet::MIN_CAPACITY, + table.GetTaggedValue().IsInSharedHeap() ? MemSpaceKind::SHARED : MemSpaceKind::LOCAL); if (table->Capacity() > 0) { table->SetNextTable(thread, newSet.GetTaggedValue()); table->SetNumberOfDeletedElements(thread, -1); diff --git a/ecmascript/linked_hash_table.h b/ecmascript/linked_hash_table.h index a567a1d29..c13ffe88e 100644 --- a/ecmascript/linked_hash_table.h +++ b/ecmascript/linked_hash_table.h @@ -47,7 +47,7 @@ public: // Don't shrink a HashTable below this capacity. static const int MIN_SHRINK_CAPACITY = 16; - static JSHandle Create(const JSThread *thread, int numberOfElements); + static JSHandle Create(const JSThread *thread, int numberOfElements, MemSpaceKind spaceKind); static JSHandle Insert(const JSThread *thread, const JSHandle &table, const JSHandle &key, const JSHandle &value); @@ -341,7 +341,8 @@ public: { return static_cast(obj); } - static JSHandle Create(const JSThread *thread, int numberOfElements = MIN_CAPACITY); + static JSHandle Create(const JSThread *thread, int numberOfElements = MIN_CAPACITY, + MemSpaceKind spaceKind = MemSpaceKind::LOCAL); static JSHandle Delete(const JSThread *thread, const JSHandle &obj, const JSHandle &key); @@ -381,7 +382,8 @@ public: { return static_cast(obj); } - static JSHandle Create(const JSThread *thread, int numberOfElements = MIN_CAPACITY); + static JSHandle Create(const JSThread *thread, int numberOfElements = MIN_CAPACITY, + MemSpaceKind spaceKind = MemSpaceKind::LOCAL); static JSHandle Delete(const JSThread *thread, const JSHandle &obj, const JSHandle &key); diff --git a/ecmascript/mem/space.h b/ecmascript/mem/space.h index e59f9a228..11eed4f29 100644 --- a/ecmascript/mem/space.h +++ b/ecmascript/mem/space.h @@ -54,6 +54,11 @@ enum MemSpaceType { SHARED_SWEEPING_SPACE_NUM = SHARED_SWEEPING_SPACE_END - SHARED_SWEEPING_SPACE_BEGIN + 1, }; +enum class MemSpaceKind { + LOCAL = 0, + SHARED = 1 +}; + static inline bool IsSMemSpace(MemSpaceType type) { return (type >= MemSpaceType::SHARED_BEGIN) && (type <= MemSpaceType::SHARED_END); diff --git a/ecmascript/tagged_dictionary.cpp b/ecmascript/tagged_dictionary.cpp index 4022d6024..8c52c905b 100644 --- a/ecmascript/tagged_dictionary.cpp +++ b/ecmascript/tagged_dictionary.cpp @@ -195,7 +195,7 @@ JSHandle NameDictionary::Create(const JSThread *thread, int numb JSHandle NameDictionary::CreateInSharedHeap(const JSThread *thread, int numberOfElements) { - return OrderHashTableT::Create(thread, numberOfElements, true); + return OrderHashTableT::Create(thread, numberOfElements, MemSpaceKind::SHARED); } PropertyAttributes NameDictionary::GetAttributes(int entry) const diff --git a/ecmascript/tagged_hash_table.h b/ecmascript/tagged_hash_table.h index d35a427fa..7a1f7e42f 100644 --- a/ecmascript/tagged_hash_table.h +++ b/ecmascript/tagged_hash_table.h @@ -90,7 +90,8 @@ public: return newTable; } - static JSHandle Create(const JSThread *thread, int entriesCount, bool inShareSpace = false) + static JSHandle Create(const JSThread *thread, int entriesCount, + MemSpaceKind spaceKind = MemSpaceKind::LOCAL) { ASSERT_PRINT((entriesCount > 0), "the size must be greater than zero"); auto size = static_cast(entriesCount); @@ -98,7 +99,7 @@ public: int length = Derived::GetEntryIndex(entriesCount); - JSHandle table = inShareSpace ? + JSHandle table = spaceKind == MemSpaceKind::SHARED ? JSHandle(thread->GetEcmaVM()->GetFactory()->NewSDictionaryArray(length)) : JSHandle(thread->GetEcmaVM()->GetFactory()->NewDictionaryArray(length)); table->SetEntriesCount(thread, 0); @@ -159,7 +160,8 @@ public: return table; } - JSHandle newTable = TaggedHashTable::Create(thread, newSize); + JSHandle newTable = TaggedHashTable::Create(thread, newSize, + table.GetTaggedValue().IsInSharedHeap() ? MemSpaceKind::SHARED : MemSpaceKind::LOCAL); table->Rehash(thread, *newTable); return newTable; @@ -408,9 +410,9 @@ public: } static JSHandle Create(const JSThread *thread, int numberOfElements = DEFAULT_ELEMENTS_NUMBER, - bool inShareSpace = false) + MemSpaceKind spaceKind = MemSpaceKind::LOCAL) { - JSHandle dict = HashTableT::Create(thread, numberOfElements, inShareSpace); + JSHandle dict = HashTableT::Create(thread, numberOfElements, spaceKind); dict->SetNextEnumerationIndex(thread, PropertyAttributes::INITIAL_PROPERTY_INDEX); return dict; } -- Gitee From f174abf689c8fbb50cd6e9f1785aaeba637df00a Mon Sep 17 00:00:00 2001 From: wu_zhang_da Date: Fri, 22 Mar 2024 14:42:35 +0800 Subject: [PATCH 015/202] JSNApiDestroyFuzzTest BugFix Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9APUW Signed-off-by: wu_zhang_da Change-Id: I71fe1abe316c0a0cbbc1c24660e8fb1640a06c37 --- ecmascript/compiler/aot_file/an_file_data_manager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ecmascript/compiler/aot_file/an_file_data_manager.cpp b/ecmascript/compiler/aot_file/an_file_data_manager.cpp index a2b4a5a60..611027810 100644 --- a/ecmascript/compiler/aot_file/an_file_data_manager.cpp +++ b/ecmascript/compiler/aot_file/an_file_data_manager.cpp @@ -41,6 +41,7 @@ void AnFileDataManager::SafeDestroyAllData() WriteLockHolder lock(lock_); if (loadedStub_ != nullptr) { ExecutedMemoryAllocator::DestroyBuf(loadedStub_->GetStubsMem()); + DestroyFileMapMem(loadedStub_->GetFileMapMem()); loadedStub_ = nullptr; } -- Gitee From 098f279bd3afffd322c4904c6fe4889ba2312b96 Mon Sep 17 00:00:00 2001 From: hwx1163501 Date: Fri, 22 Mar 2024 15:10:51 +0800 Subject: [PATCH 016/202] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=8D=E8=A7=84?= =?UTF-8?q?=E8=8C=83=E7=94=A8=E4=BE=8B=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwx1163501 issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9AQFH --- test/fuzztest/arrayref_fuzzer/BUILD.gn | 4 ++-- test/fuzztest/bigintrefgetwordsarraysize_fuzzer/BUILD.gn | 4 ++-- test/fuzztest/booleanrefvalue_fuzzer/BUILD.gn | 4 ++-- test/resource/js_runtime/ohos_test.xml | 5 +++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/test/fuzztest/arrayref_fuzzer/BUILD.gn b/test/fuzztest/arrayref_fuzzer/BUILD.gn index a9518cbe4..ce65517e2 100644 --- a/test/fuzztest/arrayref_fuzzer/BUILD.gn +++ b/test/fuzztest/arrayref_fuzzer/BUILD.gn @@ -18,7 +18,7 @@ import("//build/config/features.gni") import("//build/ohos.gni") ####################################fuzztest################################## -ohos_fuzztest("ArrayRefFuzzerTest") { +ohos_fuzztest("ArrayRefFuzzTest") { module_out_path = ets_runtime_output_path fuzz_config_file = "$js_root/test/fuzztest/arrayref_fuzzer" @@ -40,5 +40,5 @@ ohos_fuzztest("ArrayRefFuzzerTest") { group("fuzztest") { testonly = true deps = [] - deps += [ ":ArrayRefFuzzerTest" ] + deps += [ ":ArrayRefFuzzTest" ] } diff --git a/test/fuzztest/bigintrefgetwordsarraysize_fuzzer/BUILD.gn b/test/fuzztest/bigintrefgetwordsarraysize_fuzzer/BUILD.gn index d89f2ae9d..f33ba59bc 100644 --- a/test/fuzztest/bigintrefgetwordsarraysize_fuzzer/BUILD.gn +++ b/test/fuzztest/bigintrefgetwordsarraysize_fuzzer/BUILD.gn @@ -18,7 +18,7 @@ import("//build/config/features.gni") import("//build/ohos.gni") ##################################fuzztest##################################### -ohos_fuzztest("BigIntRefGetWordsArraySize_FuzzTest") { +ohos_fuzztest("BigIntRefGetWordsArraySizeFuzzTest") { module_out_path = ets_runtime_output_path fuzz_config_file = "$js_root/test/fuzztest/bigintrefgetwordsarraysize_fuzzer" @@ -40,5 +40,5 @@ ohos_fuzztest("BigIntRefGetWordsArraySize_FuzzTest") { group("fuzztest") { testonly = true deps = [] - deps += [ ":BigIntRefGetWordsArraySize_FuzzTest" ] + deps += [ ":BigIntRefGetWordsArraySizeFuzzTest" ] } diff --git a/test/fuzztest/booleanrefvalue_fuzzer/BUILD.gn b/test/fuzztest/booleanrefvalue_fuzzer/BUILD.gn index 91ad5f8dc..254d25f2c 100644 --- a/test/fuzztest/booleanrefvalue_fuzzer/BUILD.gn +++ b/test/fuzztest/booleanrefvalue_fuzzer/BUILD.gn @@ -18,7 +18,7 @@ import("//build/config/features.gni") import("//build/ohos.gni") ##################################fuzztest##################################### -ohos_fuzztest("BooleanRefValueFuzzerTest") { +ohos_fuzztest("BooleanRefValueFuzzTest") { module_out_path = ets_runtime_output_path fuzz_config_file = "$js_root/test/fuzztest/booleanrefvalue_fuzzer" @@ -42,5 +42,5 @@ ohos_fuzztest("BooleanRefValueFuzzerTest") { group("fuzztest") { testonly = true deps = [] - deps += [ ":BooleanRefValueFuzzerTest" ] + deps += [ ":BooleanRefValueFuzzTest" ] } diff --git a/test/resource/js_runtime/ohos_test.xml b/test/resource/js_runtime/ohos_test.xml index 75beb00b7..7a9a4db67 100755 --- a/test/resource/js_runtime/ohos_test.xml +++ b/test/resource/js_runtime/ohos_test.xml @@ -1924,6 +1924,11 @@