diff --git a/BUILD.gn b/BUILD.gn index a965de9b7c4762aabfc06f0ee6076f322d38e185..e1857c9c8b72e4c496132ed2cc444086a4075fb6 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -15,6 +15,13 @@ import("//build/config/clang/clang.gni") import("//build/ohos.gni") import("jsvm.gni") +ohos_prebuilt_etc("app_jit_enable_list") { + relative_install_dir = "jsvm" + source = "./app_jit_enable_list.conf" + part_name = "jsvm" + subsystem_name = "arkcompiler" +} + action("copy_v8") { external_deps = [] deps = [] @@ -27,6 +34,8 @@ action("copy_v8") { args = [ "--target_gen_dir", rebase_path("$target_gen_dir"), + rebase_path("//vendor/huawei/binary/artifacts/js_engine_url/"), + target_cpu, ] } @@ -62,7 +71,6 @@ ohos_prebuilt_shared_library("libv8") { install_enable = true install_images = [ "system" ] - innerapi_tags = [ "ndk" ] } config("llhttp_config") { @@ -83,150 +91,87 @@ ohos_static_library("llhttp") { part_name = "jsvm" } -config("jsvm_common_config") { - cflags = [ - "-fstack-protector-strong", - "--target=aarch64-linux-ohos", - "-march=armv8-a", - "-mfpu=neon", - "-m64", - "-msign-return-address=all", - "-pthread", - "-Wall", - "-Wextra", - "-Wno-unused-parameter", - "-fPIC", - "-Werror=unused-result", - "-O3", - "-fno-omit-frame-pointer", - "-fno-rtti", - "-fno-exceptions", - "-std=gnu++17", - "-fvisibility=hidden", - ] - - ldflags = [ "-fvisibility=hidden" ] - - defines = [] - if (use_platform_ohos && is_ohos) { - defines += [ - "TARGET_OHOS", - "ENABLE_HISYSEVENT", - ] - } - - if (enable_debug) { - cflags += [ "-g" ] - defines += [ "DEBUG" ] - } - - defines += [ - "_GLIBCXX_USE_CXX11_ABI=1", - "__STDC_FORMAT_MACROS", - "__POSIX__", - ] - - include_dirs = [ - "interface/innerkits", - "interface/kits", - "src", - ] -} - -config("jsvm_inspector_config") { - defines = [ - "ENABLE_INSPECTOR", - "HAVE_OPENSSL=1", - ] +config("public_jsvm_config") { + include_dirs = [ "interface/kits" ] } -ohos_source_set("jsvm_inspector") { - sources = jsvm_inspector_sources - include_dirs = [ "inspector" ] - - configs = [ - ":jsvm_common_config", - ":jsvm_inspector_config", +ohos_prebuilt_shared_library("libjsvm") { + deps = [ + ":app_jit_enable_list", + ":build_libjsvm", ] + public_configs = [ ":public_jsvm_config" ] + if (is_asan && use_hwasan) { + source = "$target_gen_dir/asan/libjsvm.so" + } else { + source = "$target_gen_dir/libjsvm.so" + } subsystem_name = "arkcompiler" part_name = "jsvm" - deps = [ - ":libv8", - ":llhttp", - ] + install_enable = true + install_images = [ "system" ] + innerapi_tags = [ "ndk" ] +} +action("build_libjsvm") { external_deps = [ "bounds_checking_function:libsec_static", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", "icu:shared_icui18n", "icu:shared_icuuc", + "init:libbegetutil", + "libuv:uv", "openssl:libcrypto_shared", "openssl:libssl_shared", + "resource_schedule_service:ressched_client", "zlib:libz", ] - if (jsvm_shared_libuv) { - external_deps += [ "libuv:uv" ] - } else { - external_deps += [ "libuv:uv_static" ] - } -} - -config("libjsvm_config") { - defines = [] - if (enable_inspector) { - defines += [ - "ENABLE_INSPECTOR", - "HAVE_OPENSSL=1", - ] - } -} - -config("public_jsvm_config") { - include_dirs = [ "interface/kits" ] -} - -ohos_shared_library("libjsvm") { - sources = jsvm_sources - public_configs = [ ":public_jsvm_config" ] - if (use_platform_ohos && is_ohos) { - sources += [ "src/platform/platform_ohos.cpp" ] + deps = [ + ":libv8", + ":llhttp", + ] + configs = [] + script = "build_jsvm.sh" + sources = [] + if (is_asan && use_hwasan) { + outputs = [ "$target_gen_dir/asan/libjsvm.so" ] } else { - sources += [ "src/platform/platform.cpp" ] + outputs = [ "$target_gen_dir/libjsvm.so" ] } - configs = [ - ":jsvm_common_config", - ":libjsvm_config", + args = [ + "--target_gen_dir", + rebase_path("$target_gen_dir"), + "--target_out_dir", + rebase_path("$root_out_dir"), + "--target_cpu", + "$target_cpu", + "--target_platform", + "$target_platform", + "--prefix", + rebase_path("$clang_base_path/bin"), + "--sysroot", + rebase_path("$musl_sysroot"), + "--is_asan", + "$is_asan", + "--use_hwasan", + "$use_hwasan", + "{{include_dirs}}", + "--cmake_path", + rebase_path("//prebuilts/cmake/linux-x86/bin/cmake"), + "--jsvm_path", + rebase_path("."), ] - - deps = [ ":libv8" ] - if (enable_inspector) { - deps += [ ":jsvm_inspector" ] - } - - external_deps = [] - - if (use_platform_ohos && is_ohos) { - external_deps += [ - "bounds_checking_function:libsec_static", - "hilog:libhilog", - "hisysevent:libhisysevent", - "hitrace:hitrace_meter", - "init:libbegetutil", - "resource_schedule_service:ressched_client", + if (use_clang_coverage) { + args += [ + "--target_clang_coverage", + "$use_clang_coverage", ] } - - output_name = "libjsvm" - output_extension = "so" - - subsystem_name = "arkcompiler" - part_name = "jsvm" - - install_enable = true - install_images = [ "system" ] - innerapi_tags = [ "ndk" ] } group("jsvm_packages") { diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..1f46741419cf8c74ad1a547b6370ca365f3fd8b7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,125 @@ +cmake_minimum_required(VERSION 3.28) + +# 设置项目名称 +project(JSVM) + +# 设置C++标准 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# 添加编译选项 +add_compile_options( + -fstack-protector-strong + -msign-return-address=all + -pthread + -Wall + -Wextra + -Wno-unused-parameter + -fPIC + -Werror=unused-result + -O3 + -fno-omit-frame-pointer + -fno-rtti + -fno-exceptions + -fvisibility=hidden +) + +if ((DEFINED TARGET_CPU) AND (${TARGET_CPU} MATCHES "arm")) + add_compile_options( + -mbranch-protection=pac-ret+b-key+bti + ) +endif() + +# 设置宏定义 +add_compile_definitions( + -DENABLE_INSPECTOR + -DHAVE_OPENSSL=1 + -DTARGET_OHOS + -DENABLE_HISYSEVENT +) + +# 添加头文件 +include_directories(jsvm + "src" + "interface/kits" +) + +# 设置源文件 +set (jsvm_sources + "src/js_native_api_v8.cpp" + "src/jsvm_env.cpp" + "src/jsvm_reference.cpp" +) + +set (jsvm_inspector_sources + "src/inspector/inspector_socket.cpp" + "src/inspector/inspector_socket_server.cpp" + "src/inspector/inspector_utils.cpp" + "src/inspector/js_native_api_v8_inspector.cpp" +) + +set (platform_sources + "src/platform/platform_ohos.cpp" +) + +# 添加动态库搜索路径 +set (LIB_DIRS + "${LIB_ROOT_DIR}/obj/arkcompiler/jsvm" + "${LIB_ROOT_DIR}/obj/third_party/zlib" + "${LIB_ROOT_DIR}/hiviewdfx/hilog_override" + "${LIB_ROOT_DIR}/hiviewdfx/hilog" + "${LIB_ROOT_DIR}/resourceschedule/resource_schedule_service" + "${LIB_ROOT_DIR}/startup/init" + "${LIB_ROOT_DIR}/hiviewdfx/hitrace/" + "${LIB_ROOT_DIR}/thirdparty/libuv/" + "${LIB_ROOT_DIR}/thirdparty/icu/" + "${LIB_ROOT_DIR}/thirdparty/openssl/" + "${LIB_ROOT_DIR}/obj/vendor/huawei/foundation/bundlemanager/zlib_override/" +) +set(CMAKE_SKIP_RPATH TRUE) +link_directories(${LIB_DIRS}) + +# 添加目标 +add_library(jsvm + SHARED + ${platform_sources} + ${jsvm_sources} + ${jsvm_inspector_sources} +) + +target_link_options(jsvm + PRIVATE + "-Wl,--exclude-libs=libc++_static.a" +) + +if ((DEFINED USE_LIBZ_INNER) AND USE_LIBZ_INNER) +target_link_libraries(jsvm + libz_inner.a + libllhttp.a + libressched_client.z.so + libbegetutil.z.so + libhitrace_meter.so + libuv.so + libhmicuuc.z.so + libhmicui18n.z.so + libcrypto_openssl.z.so + libssl_openssl.z.so + libv8_shared.so + libhilog.so +) +else() +target_link_libraries(jsvm + libz.a + libllhttp.a + libressched_client.z.so + libbegetutil.z.so + libhitrace_meter.so + libuv.so + libhmicuuc.z.so + libhmicui18n.z.so + libcrypto_openssl.z.so + libssl_openssl.z.so + libv8_shared.so + libhilog.so +) +endif() diff --git a/app_jit_enable_list.conf b/app_jit_enable_list.conf new file mode 100644 index 0000000000000000000000000000000000000000..87cb901718338a182511b0d5f5626d31f9ce4850 --- /dev/null +++ b/app_jit_enable_list.conf @@ -0,0 +1,62 @@ +com.dingtalk.hmos +com.jd.hm.mall +com.sankuai.hmeituan +com.sankuai.dianping +com.vip.hosapp +com.suanya.harmonynext +com.meituan.takeaway +com.tencent.videohm +com.jd.jrapp.hongmeng +com.ctrip.harmonynext +com.cainiao.cainiao4hmos +com.tencent.hm.news +com.fliggy.hmos +yylx.danmaku.bili +com.cmcc.cmvideohm +com.taobao.taobao4hmos +com.klfe.hos.kmall +net.vipmro.activity.hos +com.sihai.jiujiuxiaogouhm.huawei +io.dcloud.hellouniapp.h +com.zengame.ttaxq.hm +com.maoyan.hmovie +com.kuaishou.hmapp +com.xingpianhao.miluhms +com.aibotshengma.harm +com.hm.manyi.tms.driver +com.mihuan.mgsshos.huawei +com.roborock.smart.hm +com.ahsq.dldl.sysqharmony +com.mvtrail.notepad.zjhw +com.party.zhdj.hm +com.Csai.CsaiApp +com.loafish.znyerp +cn.samsclub.hm.app +com.dewu.hos +com.jianli.zhizuobaoshms +com.bjy.app +com.meituan.hiyouxuan +com.bendibao.app +com.shangxueba.open.sxbhm +com.sc.meihao +com.whaty.HMRXZX +com.meituan.hmaicai +com.aichatsm.harm +cn.yorry.sudoku +com.dsy.ymygz +meet.popsoft.tech +com.tencent.hmportfolio +com.cgs.gov.geoapp +com.sjfc.whfyt.harm +hmos.com.qxnga.qjt +com.fulfut.read.har +com.mvtrail.tibetantranslator.zjhw +com.xunji.hm +com.huayimt.hm +cn.kunming.railway.krplus.hm +com.huawei.hmos.vmall +com.huawei.hmsapp.litegamelauncher +com.atomicservice.5765880207855215271 +com.atomicservice.5765880207855116497 +com.atomicservice.5765880207856089841 +com.acts.ace.napitest diff --git a/build_jsvm_inter.sh b/build_jsvm_inter.sh index 7148ee20c82b7f0ba4ea9029e73f427faa44b014..33cbb495a3e239920e44f4797b35d7a25cad57be 100755 --- a/build_jsvm_inter.sh +++ b/build_jsvm_inter.sh @@ -24,10 +24,11 @@ do_patch() { do_configure() { use_libz_inner=0 - + if [ -f "${LIB_ROOT_DIR}/obj/vendor/huawei/foundation/bundlemanager/zlib_override/libz_inner.a" ];then use_libz_inner=1 fi + ${CMAKE_PATH} \ -DLIB_ROOT_DIR=${LIB_ROOT_DIR}\ -DTARGET_CPU=${TARGET_CPU}\ @@ -115,7 +116,7 @@ do_install_asan() { mkdir -p ${TARGET_GEN_DIR}/asan cp -u ${workdir}/libjsvm.so ${TARGET_GEN_DIR}/asan cp -u ${JSVM_PATH}/../../vendor/huawei/binary/artifacts/js_engine_url/v8/${TARGET_CPU}/lib.unstripped_v8/lib.unstripped/libv8_shared.so ${TARGET_GEN_DIR}/asan - + mkdir -p ${TARGET_GEN_DIR}/../../../../../lib.unstripped/jsvm/ cp -u ${workdir}/libjsvm.so ${TARGET_GEN_DIR}/../../../../../lib.unstripped/jsvm/ cp -u ${JSVM_PATH}/../../vendor/huawei/binary/artifacts/js_engine_url/v8/${TARGET_CPU}/lib.unstripped_v8/lib.unstripped/libv8_shared.so ${TARGET_GEN_DIR}/../../../../../lib.unstripped/jsvm/ diff --git a/interface/kits/jsvm_types.h b/interface/kits/jsvm_types.h index e99aef864e9104cfa158981292d199b13b2a0f17..7cf33b497858d72005456d5c6a14929f81cff098 100644 --- a/interface/kits/jsvm_types.h +++ b/interface/kits/jsvm_types.h @@ -326,7 +326,11 @@ typedef enum { /** invalid input type status. * @since 18 */ - JSVM_INVALID_TYPE + JSVM_INVALID_TYPE, + /** jit mode expected status. + * @since 15 + */ + JSVM_JIT_MODE_EXPECTED, } JSVM_Status; /** diff --git a/src/js_native_api_v8.cpp b/src/js_native_api_v8.cpp index a3a042e5ccc60930ad5b78fe746086f47ff2714b..7ba4d7c29edae5f7fba07c9d80d321fb2310cd8b 100644 --- a/src/js_native_api_v8.cpp +++ b/src/js_native_api_v8.cpp @@ -1009,11 +1009,10 @@ JSVM_Status OH_JSVM_Init(const JSVM_InitOptions* options) OHOS_API_CALL(platform::ohos::ReportKeyThread(platform::ohos::ThreadRole::IMPORTANT_DISPLAY)); v8::V8::InitializePlatform(v8impl::g_platform.get()); - OHOS_API_CALL(platform::ohos::SetSecurityMode()); - if (options && options->argc && options->argv) { v8::V8::SetFlagsFromCommandLine(options->argc, options->argv, options->removeFlags); } + OHOS_API_CALL(platform::ohos::SetSecurityMode()); v8::V8::Initialize(); const auto cb = v8impl::FunctionCallbackWrapper::Invoke; @@ -1408,7 +1407,7 @@ public: bool hasInvalidOption = false; private: - v8::ScriptCompiler::CompileOptions jsvmToOptions[] = { + static constexpr v8::ScriptCompiler::CompileOptions jsvmToOptions[] = { v8::ScriptCompiler::kNoCompileOptions, v8::ScriptCompiler::kConsumeCodeCache, v8::ScriptCompiler::kEagerCompile, @@ -1714,6 +1713,7 @@ static const char* errorMessages[] = { "External buffers are not allowed", "Cannot run JavaScript", "Invalid type", + "Cannot run in Jitless Mode", }; JSVM_Status OH_JSVM_GetLastErrorInfo(JSVM_Env env, const JSVM_ExtendedErrorInfo** result) @@ -1725,7 +1725,7 @@ JSVM_Status OH_JSVM_GetLastErrorInfo(JSVM_Env env, const JSVM_ExtendedErrorInfo* // message in the `JSVM_Status` enum each time a new error message is added. // We don't have a jsvm_status_last as this would result in an ABI // change each time a message was added. - const int lastStatus = JSVM_INVALID_TYPE; + const int lastStatus = JSVM_JIT_MODE_EXPECTED; static_assert(jsvm::ArraySize(errorMessages) == lastStatus + 1, "Count of error messages must match count of error values"); @@ -4587,6 +4587,8 @@ JSVM_Status OH_JSVM_CompileWasmModule(JSVM_Env env, JSVM_Value* wasmModule) { JSVM_PREAMBLE(env); + // add jit mode check + RETURN_STATUS_IF_FALSE(env, platform::ohos::InJitMode(), JSVM_JIT_MODE_EXPECTED); CHECK_ARG(env, wasmBytecode); RETURN_STATUS_IF_FALSE(env, wasmBytecodeLength > 0, JSVM_INVALID_ARG); v8::MaybeLocal maybeModule; @@ -4614,7 +4616,10 @@ JSVM_Status OH_JSVM_CompileWasmFunction(JSVM_Env env, JSVM_WasmOptLevel optLevel) { JSVM_PREAMBLE(env); + // add jit mode check + RETURN_STATUS_IF_FALSE(env, platform::ohos::InJitMode(), JSVM_JIT_MODE_EXPECTED); CHECK_ARG(env, wasmModule); + v8::Local val = v8impl::V8LocalValueFromJsValue(wasmModule); RETURN_STATUS_IF_FALSE(env, val->IsWasmModuleObject(), JSVM_INVALID_ARG); @@ -4653,6 +4658,8 @@ JSVM_Status OH_JSVM_IsWasmModuleObject(JSVM_Env env, JSVM_Value value, bool* res JSVM_Status OH_JSVM_CreateWasmCache(JSVM_Env env, JSVM_Value wasmModule, const uint8_t** data, size_t* length) { JSVM_PREAMBLE(env); + // add jit mode check + RETURN_STATUS_IF_FALSE(env, platform::ohos::InJitMode(), JSVM_JIT_MODE_EXPECTED); CHECK_ARG(env, wasmModule); CHECK_ARG(env, data); CHECK_ARG(env, length); diff --git a/src/platform/platform_ohos.cpp b/src/platform/platform_ohos.cpp index dd2d387782de3afbdb8c84e931f8fc71b0856834..c92784f02b78f701d39dcd68434fdf80a97b792a 100644 --- a/src/platform/platform_ohos.cpp +++ b/src/platform/platform_ohos.cpp @@ -27,7 +27,11 @@ #ifdef ENABLE_HISYSEVENT #include "hisysevent.h" #endif +#include +#include +#include +#define USE_C_API namespace platform { void OS::Abort() { @@ -110,7 +114,80 @@ RunJsTrace::~RunJsTrace() } } +#ifdef USE_C_API +namespace ResourceSchedule { +namespace ResType { +extern "C" void ReportData(uint32_t resType, + int64_t value, + const std::unordered_map& mapPayLoad); + +enum : uint32_t { RES_TYPE_REPORT_KEY_THREAD = 39 }; + +enum ReportChangeStatus : int64_t { CREATE = 0, REMOVE = 1 }; + +enum ThreadRole : int64_t { + USER_INTERACT = 0, + NORMAL_DISPLAY = 1, + IMPORTANT_DISPLAY = 2, + NORMAL_AUDIO = 3, + IMPORTANT_AUDIO = 4, + IMAGE_DECODE = 5 +}; +} // namespace ResType +} // namespace ResourceSchedule +#endif + +static bool isJitMode = true; namespace ohos { +#define JITFORT_QUERY_ENCAPS 'E' +#define HM_PR_SET_JITFORT 0x6a6974 + +const std::string ENABLE_JIT_CONF_PATH = "/etc/jsvm/app_jit_enable_list.conf"; +bool ProcessBundleName(std::string& bundleName); + +void ReadEnableList(const std::string& jitConfigPath, std::unordered_set& enableSet) +{ + std::ifstream file(jitConfigPath); + if (file.is_open()) { + std::string line; + while (std::getline(file, line)) { + if (!line.empty()) { + enableSet.insert(line); + } + } + file.close(); + } +} + +bool InJitMode() +{ + return isJitMode; +} + +inline bool InAppEnableList(const std::string& bundleName, std::unordered_set& enableSet) +{ + return (enableSet.count(bundleName) != 0); +} + +inline bool HasJitfortACL() +{ + return (prctl(HM_PR_SET_JITFORT, JITFORT_QUERY_ENCAPS, 0) == 0); +} + +#ifdef USE_C_API +void ReportKeyThread(ThreadRole role) +{ + uint64_t uid = OS::GetUid(); + uint64_t tid = OS::GetTid(); + uint64_t pid = OS::GetPid(); + std::unordered_map payLoad = { { "uid", std::to_string(uid) }, + { "pid", std::to_string(pid) }, + { "tid", std::to_string(tid) }, + { "role", std::to_string(role) } }; + ReportData(ResourceSchedule::ResType::RES_TYPE_REPORT_KEY_THREAD, + ResourceSchedule::ResType::ReportChangeStatus::CREATE, payLoad); +} +#else void ReportKeyThread(ThreadRole role) { static_assert(static_cast(ThreadRole::IMPORTANT_DISPLAY) == @@ -129,6 +206,7 @@ void ReportKeyThread(ThreadRole role) OHOS::ResourceSchedule::ResType::RES_TYPE_REPORT_KEY_THREAD, OHOS::ResourceSchedule::ResType::ReportChangeStatus::CREATE, payLoad); } +#endif inline bool ReadSystemXpmState() { @@ -145,7 +223,15 @@ inline bool ReadSystemXpmState() void SetSecurityMode() { constexpr size_t secArgCnt = 2; - if (ReadSystemXpmState()) { + std::string bundleName; + if (!ProcessBundleName(bundleName)) { + bundleName = "INVALID_BUNDLE_NAME"; + } + std::unordered_set enableList {}; + ReadEnableList(ENABLE_JIT_CONF_PATH, enableList); + + if (ReadSystemXpmState() || (!InAppEnableList(bundleName, enableList) && !HasJitfortACL())) { + isJitMode = false; int secArgc = secArgCnt; constexpr bool removeFlag = false; const char* secArgv[secArgCnt] = { "jsvm", "--jitless" }; diff --git a/src/platform/platform_ohos.h b/src/platform/platform_ohos.h index 46628592b38704ad046c59979e6c73264665d548..c89daaad88eedb563e2261e655330b25f3f56721 100644 --- a/src/platform/platform_ohos.h +++ b/src/platform/platform_ohos.h @@ -35,6 +35,8 @@ void ReportKeyThread(ThreadRole role); void SetSecurityMode(); void WriteHisysevent(); + +bool InJitMode(); } // namespace ohos } // namespace platform -#endif \ No newline at end of file +#endif