diff --git a/ecmascript/compiler/aot_compiler.cpp b/ecmascript/compiler/aot_compiler.cpp index 160ddc492f..9bd8a4a701 100644 --- a/ecmascript/compiler/aot_compiler.cpp +++ b/ecmascript/compiler/aot_compiler.cpp @@ -28,6 +28,7 @@ #include "ecmascript/log.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/napi/include/jsnapi.h" +#include "ecmascript/ohos/enable_aot_list_helper.h" #include "ecmascript/ohos/ohos_pkg_args.h" #include "ecmascript/platform/file.h" #include "ecmascript/platform/os.h" @@ -220,6 +221,7 @@ int Main(const int argc, const char **argv) if (runtimeOptions.IsTargetCompilerMode()) { compilerStats.PrintCompilerStatsLog(); } + ohos::EnableAotListHelper::GetInstance()->AddEnableListCount(cPreprocessor.GetMainPkgArgs()->GetPgoDir()); } LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed"); diff --git a/ecmascript/dfx/stackinfo/js_stackinfo.cpp b/ecmascript/dfx/stackinfo/js_stackinfo.cpp index a199de6be1..a0893c415b 100644 --- a/ecmascript/dfx/stackinfo/js_stackinfo.cpp +++ b/ecmascript/dfx/stackinfo/js_stackinfo.cpp @@ -24,6 +24,7 @@ #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/mem/heap-inl.h" #include "ecmascript/message_string.h" +#include "ecmascript/ohos/aot_runtime_info.h" #include "ecmascript/platform/os.h" #if defined(PANDA_TARGET_OHOS) #include "ecmascript/extractortool/src/extractor.h" @@ -34,10 +35,6 @@ namespace panda::ecmascript { [[maybe_unused]] static bool g_needCheck = true; - -const int USEC_PER_SEC = 1000 * 1000; -const int NSEC_PER_USEC = 1000; - std::unordered_map JsStackInfo::nameMap; std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile) @@ -147,60 +144,22 @@ std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative) return data; } -uint64_t GetMicrosecondsTimeStamp() -{ - struct timespec time; - clock_gettime(CLOCK_MONOTONIC, &time); - return time.tv_sec * USEC_PER_SEC + time.tv_nsec / NSEC_PER_USEC; -} - void JsStackInfo::BuildCrashInfo(bool isJsCrash, uintptr_t pc) { if (JsStackInfo::loader != nullptr && !JsStackInfo::loader->IsEnableAOT() && JsStackInfo::options != nullptr && !JsStackInfo::options->IsEnableJIT()) { return; } - std::string realOutPath; - std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(ohos::AotCrashInfo::GetSandBoxPath()); - if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) { - return; - } - uint64_t timestamp = GetMicrosecondsTimeStamp(); - ohos::AotCrashInfo aotCrashInfo; - std::string soBuildId = aotCrashInfo.GetRuntimeBuildId(); - if (soBuildId == "") { - LOG_ECMA(ERROR) << "can't get so buildId"; - return; - } - realOutPath = realOutPath + "/" + ohos::AotCrashInfo::GetCrashFileName(); - std::ifstream ifile(realOutPath.c_str()); - std::vector lines; - if (ifile.is_open()) { - std::string iline; - while (ifile >> iline) { - std::string buildId = ohos::AotCrashInfo::GetBuildId(iline); - if (buildId != soBuildId) { - continue; - } - lines.emplace_back(iline); - } - ifile.close(); - } - ohos::CrashType type; + ohos::RuntimeInfoType type; if (isJsCrash) { - type = ohos::CrashType::JS; + type = ohos::RuntimeInfoType::JS; } else if (pc != 0 && JsStackInfo::loader != nullptr && JsStackInfo::loader->InsideAOT(pc)) { - type = ohos::CrashType::AOT; + type = ohos::RuntimeInfoType::AOT; } else { - type = ohos::CrashType::OTHERS; + type = ohos::RuntimeInfoType::OTHERS; } - std::string buildLine = ohos::AotCrashInfo::BuildAotCrashInfo(soBuildId, std::to_string(timestamp), type); - lines.emplace_back(buildLine); - std::ofstream file(realOutPath.c_str(), std::ofstream::out); - for (const std::string& line : lines) { - file << line << "\n"; - } - file.close(); + ohos::AotRuntimeInfo aotRuntimeInfo; + aotRuntimeInfo.BuildCrashRuntimeInfo(ohos::AotRuntimeInfo::GetRuntimeInfoTypeStr(type)); } std::vector JsStackInfo::BuildJsStackInfo(JSThread *thread, bool currentStack) diff --git a/ecmascript/dfx/stackinfo/js_stackinfo.h b/ecmascript/dfx/stackinfo/js_stackinfo.h index 80b8641f1c..e2b8c3e71f 100644 --- a/ecmascript/dfx/stackinfo/js_stackinfo.h +++ b/ecmascript/dfx/stackinfo/js_stackinfo.h @@ -19,7 +19,6 @@ #include #include "ecmascript/compiler/aot_file/aot_file_manager.h" #include "ecmascript/extractortool/src/source_map.h" -#include "ecmascript/ohos/aot_crash_info.h" #include "ecmascript/js_thread.h" #include "ecmascript/jspandafile/js_pandafile_manager.h" #include "ecmascript/dfx/dump_code/jit_dump_elf.h" @@ -165,7 +164,6 @@ public: static std::unordered_map nameMap; }; void CrashCallback(char *buf, size_t len, void *ucontext); -uint64_t GetMicrosecondsTimeStamp(); } // namespace panda::ecmascript #endif // ECMASCRIPT_DFX_STACKINFO_JS_STACKINFO_H extern "C" int step_ark_managed_native_frame( diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 435d255dd2..22b626964d 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -231,8 +231,13 @@ void EcmaVM::PostFork() } else if (ohos::EnableAotListHelper::GetInstance()->IsEnableList(bundleName)) { options_.SetEnablePGOProfiler(true); } + if (ohos::EnableAotListHelper::GetInstance()->IsAotCompileSuccessOnce()) { + options_.SetEnablePGOProfiler(false); + LOG_ECMA(INFO) << "Aot has compile success once."; + } if (JSNApi::IsAotEscape()) { options_.SetEnablePGOProfiler(false); + LOG_ECMA(INFO) << "Aot has escaped."; } ResetPGOProfiler(); diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index 3bb762c08c..1dbb80d2e9 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -93,6 +93,7 @@ #include "ecmascript/js_weak_container.h" #include "ecmascript/ohos/aot_crash_info.h" #include "ecmascript/ohos/framework_helper.h" +#include "ecmascript/ohos/aot_runtime_info.h" #ifdef ARK_SUPPORT_INTL #include "ecmascript/js_bigint.h" #include "ecmascript/js_collator.h" @@ -199,7 +200,6 @@ using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager; using FrameIterator = ecmascript::FrameIterator; using Concurrent = ecmascript::Concurrent; using CrashInfo = ecmascript::ohos::AotCrashInfo; -using CrashType = ecmascript::ohos::CrashType; namespace { // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) @@ -4268,51 +4268,26 @@ bool JSNApi::KeyIsNumber(const char* utf8) return true; } -std::map CollectCrashSum() -{ - std::map escapeMap; - std::string realOutPath; - std::string arkProfilePath = CrashInfo::GetSandBoxPath(); - std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(arkProfilePath); - if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) { - return escapeMap; - } - realOutPath = realOutPath + "/" + CrashInfo::GetCrashFileName(); - CrashInfo aotCrashInfo; - std::string soBuildId = aotCrashInfo.GetRuntimeBuildId(); - std::ifstream ifile(realOutPath.c_str()); - if (ifile.is_open()) { - std::string iline; - while (ifile >> iline) { - std::string buildId = CrashInfo::GetBuildId(iline); - CrashType type = CrashInfo::GetCrashType(iline); - if (buildId == soBuildId) { - escapeMap[type]++; - } - } - ifile.close(); - } - return escapeMap; -} - bool JSNApi::IsAotEscape() { if (CrashInfo::GetAotEscapeDisable()) { return false; } - auto escapeMap = CollectCrashSum(); - return escapeMap[CrashType::AOT] >= CrashInfo::GetAotCrashCount() || - escapeMap[CrashType::OTHERS] >= CrashInfo::GetOthersCrashCount() || - escapeMap[CrashType::JS] >= CrashInfo::GetJsCrashCount(); + ecmascript::ohos::AotRuntimeInfo aotRuntimeInfo; + auto escapeMap = aotRuntimeInfo.CollectCrashSum(); + return escapeMap[ecmascript::ohos::RuntimeInfoType::AOT] >= CrashInfo::GetAotCrashCount() || + escapeMap[ecmascript::ohos::RuntimeInfoType::OTHERS] >= CrashInfo::GetOthersCrashCount() || + escapeMap[ecmascript::ohos::RuntimeInfoType::JS] >= CrashInfo::GetJsCrashCount(); } bool JSNApi::IsJitEscape() { - auto escapeMap = CollectCrashSum(); - return escapeMap[CrashType::JIT] >= CrashInfo::GetJitCrashCount() || - escapeMap[CrashType::AOT] >= CrashInfo::GetAotCrashCount() || - escapeMap[CrashType::OTHERS] >= CrashInfo::GetOthersCrashCount() || - escapeMap[CrashType::JS] >= CrashInfo::GetJsCrashCount(); + ecmascript::ohos::AotRuntimeInfo aotRuntimeInfo; + auto escapeMap = aotRuntimeInfo.CollectCrashSum(); + return escapeMap[ecmascript::ohos::RuntimeInfoType::JIT] >= CrashInfo::GetJitCrashCount() || + escapeMap[ecmascript::ohos::RuntimeInfoType::AOT] >= CrashInfo::GetAotCrashCount() || + escapeMap[ecmascript::ohos::RuntimeInfoType::OTHERS] >= CrashInfo::GetOthersCrashCount() || + escapeMap[ecmascript::ohos::RuntimeInfoType::JS] >= CrashInfo::GetJsCrashCount(); } bool JSNApi::IsSerializationTimeoutCheckEnabled(const EcmaVM *vm) diff --git a/ecmascript/ohos/aot_crash_info.h b/ecmascript/ohos/aot_crash_info.h index f00598378f..56b9d33330 100644 --- a/ecmascript/ohos/aot_crash_info.h +++ b/ecmascript/ohos/aot_crash_info.h @@ -16,36 +16,20 @@ #ifndef ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H #define ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H +#include "ohos_constants.h" #include "ecmascript/base/string_helper.h" -#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) +#ifdef AOT_ESCAPE_ENABLE #include "parameters.h" #endif namespace panda::ecmascript::ohos { -#define CRASH_TYPE(V) \ - V(AOT) \ - V(OTHERS) \ - V(NONE) \ - V(JIT) \ - V(JS) \ - -enum class CrashType { - AOT, - JIT, - OTHERS, - NONE, - JS, -}; class AotCrashInfo { - constexpr static const char *const SANDBOX_ARK_PROFILE_PATH = "/data/storage/ark-profile"; constexpr static const char *const CRASH_FILE_NAME = "aot_crash.log"; - constexpr static const char *const RUNTIME_SO_PATH = "/system/lib64/platformsdk/libark_jsruntime.so"; constexpr static const char *const SPLIT_STR = "|"; constexpr static const char *const AOT_ESCAPE_DISABLE = "ark.aot.escape.disable"; constexpr static int AOT_CRASH_COUNT = 1; constexpr static int OTHERS_CRASH_COUNT = 3; constexpr static int CRASH_LOG_SIZE = 3; - constexpr static int NT_GNU_BUILD_ID = 3; constexpr static int JIT_CRASH_COUNT = 1; constexpr static int JS_CRASH_COUNT = 3; public: @@ -53,26 +37,9 @@ public: explicit AotCrashInfo() = default; virtual ~AotCrashInfo() = default; - static CrashType GetCrashType(std::string crashInfo) - { - std::vector splitCrashInfo = base::StringHelper::SplitString(crashInfo, SPLIT_STR); - if (splitCrashInfo.size() == CRASH_LOG_SIZE) { - if (splitCrashInfo[CRASH_LOG_SIZE - 1] == GetCrashTypeStr(CrashType::AOT)) { - return CrashType::AOT; - } else if (splitCrashInfo[CRASH_LOG_SIZE - 1] == GetCrashTypeStr(CrashType::JIT)) { - return CrashType::JIT; - } else if (splitCrashInfo[CRASH_LOG_SIZE - 1] == GetCrashTypeStr(CrashType::JS)) { - return CrashType::JS; - } else if (splitCrashInfo[CRASH_LOG_SIZE - 1] == GetCrashTypeStr(CrashType::OTHERS)) { - return CrashType::OTHERS; - } - } - return CrashType::NONE; - } - static bool GetAotEscapeDisable() { -#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) +#ifdef AOT_ESCAPE_ENABLE return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false); #endif return false; @@ -80,7 +47,7 @@ public: static std::string GetSandBoxPath() { - return SANDBOX_ARK_PROFILE_PATH; + return OhosConstants::SANDBOX_ARK_PROFILE_PATH; } static std::string GetCrashFileName() @@ -107,150 +74,6 @@ public: { return OTHERS_CRASH_COUNT; } - - static std::string GetCrashTypeStr(CrashType type) - { - const std::map strMap = { -#define CRASH_TYPE_MAP(name) { CrashType::name, #name }, - CRASH_TYPE(CRASH_TYPE_MAP) -#undef CRASH_TYPE_MAP - }; - if (strMap.count(type) > 0) { - return strMap.at(type); - } - return ""; - } - - static CrashType GetCrashTypeByStr(std::string crashType) - { - const std::map strMap = { -#define CRASH_TYPE_MAP(name) { #name, CrashType::name }, - CRASH_TYPE(CRASH_TYPE_MAP) -#undef CRASH_TYPE_MAP - }; - if (strMap.count(crashType) > 0) { - return strMap.at(crashType); - } - return CrashType::NONE; - } - - static std::string BuildAotCrashInfo(std::string buildId, std::string timestamp, CrashType type) - { - return buildId + SPLIT_STR + timestamp + SPLIT_STR + GetCrashTypeStr(type); - } - - static std::string GetBuildId(std::string crashInfo) - { - std::vector splitCrashInfo = base::StringHelper::SplitString(crashInfo, SPLIT_STR); - if (splitCrashInfo.size() == CRASH_LOG_SIZE) { - return splitCrashInfo[0]; - } - return ""; - } - - std::string GetRuntimeBuildId() - { - std::string realPath; - if (!FileExist(RUNTIME_SO_PATH)) { - return ""; - } - std::string soPath = panda::os::file::File::GetExtendedFilePath(RUNTIME_SO_PATH); - if (!ecmascript::RealPath(soPath, realPath, false)) { - return ""; - } - if (!FileExist(realPath.c_str())) { - return ""; - } - fileMap = ecmascript::FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ); - if (fileMap.GetOriginAddr() == nullptr) { - return ""; - } - ecmascript::PagePreRead(fileMap.GetOriginAddr(), fileMap.GetSize()); - return ParseELFSectionsForBuildId(); - } - -private: - std::string GetReadableBuildId(std::string &buildIdHex) - { - if (buildIdHex.empty()) { - return ""; - } - static const char HEXTABLE[] = "0123456789abcdef"; - static const int HEXLENGTH = 16; - static const int HEX_EXPAND_PARAM = 2; - const size_t len = buildIdHex.length(); - std::string buildId(len * HEX_EXPAND_PARAM, '\0'); - - for (size_t i = 0; i < len; i++) { - unsigned int n = buildIdHex[i]; - buildId[i * HEX_EXPAND_PARAM] = HEXTABLE[(n >> 4) % HEXLENGTH]; // 4 : higher 4 bit of uint8 - buildId[i * HEX_EXPAND_PARAM + 1] = HEXTABLE[n % HEXLENGTH]; - } - return buildId; - } - - uint64_t AlignValues(uint64_t val, uint64_t align) - { - return (val + AlignBytes(align)) & AlignMask(align); - } - - uint64_t AlignMask(uint64_t align) - { - return ~(static_cast((align) - 1)); - } - - uint64_t AlignBytes(uint64_t align) - { - return (align) - 1; - } - - std::string ParseELFSectionsForBuildId() - { - llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast(fileMap.GetOriginAddr()); - char *addr = reinterpret_cast(ehdr); - llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast(addr + ehdr->e_shoff); - ASSERT(ehdr->e_shstrndx != static_cast(-1)); - llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx]; - int secId = -1; - std::string sectionName = ".note.gnu.build-id"; - for (size_t i = 0; i < ehdr->e_shnum; i++) { - llvm::ELF::Elf64_Word shName = shdr[i].sh_name; - char *curShName = reinterpret_cast(addr) + shName + strdr.sh_offset; - if (sectionName.compare(curShName) == 0) { - secId = static_cast(i); - break; - } - } - if (secId == -1) { - return ""; - } - llvm::ELF::Elf64_Shdr secShdr = shdr[secId]; - uint64_t buildIdOffset = secShdr.sh_offset; - uint64_t buildIdSize = secShdr.sh_size; - llvm::ELF::Elf64_Nhdr *nhdr = reinterpret_cast(addr + buildIdOffset); - char *curShNameForNhdr = reinterpret_cast(addr + buildIdOffset + sizeof(*nhdr)); - if (buildIdSize - sizeof(*nhdr) < nhdr->n_namesz) { - return ""; - } - std::string curShNameStr = curShNameForNhdr; - if (curShNameStr.back() == '\0') { - curShNameStr.resize(curShNameStr.size() - 1); - } - - if (curShNameStr != "GNU" || nhdr->n_type != NT_GNU_BUILD_ID) { - return ""; - } - if (buildIdSize - sizeof(*nhdr) - AlignValues(nhdr->n_namesz, 4) < nhdr->n_descsz || nhdr->n_descsz == 0) { - return ""; - } - - char *curShNameValueForNhdr = reinterpret_cast(addr + buildIdOffset + sizeof(*nhdr) - + AlignValues(nhdr->n_namesz, 4)); - std::string curShNameValueForNhdrStr = curShNameValueForNhdr; - return GetReadableBuildId(curShNameValueForNhdrStr); - } - - ecmascript::MemMap fileMap; }; } // namespace panda::ecmascript #endif // ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H diff --git a/ecmascript/ohos/aot_runtime_info.h b/ecmascript/ohos/aot_runtime_info.h new file mode 100644 index 0000000000..687d50d510 --- /dev/null +++ b/ecmascript/ohos/aot_runtime_info.h @@ -0,0 +1,330 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H +#define ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H + +#include + +#include "ecmascript/platform/directory.h" +#include "ecmascript/platform/file.h" +#include "ecmascript/platform/map.h" +#include "ecmascript/ohos/aot_crash_info.h" +#include "libpandafile/file.h" +#include "llvm/BinaryFormat/ELF.h" +#include "ohos_constants.h" + +namespace panda::ecmascript::ohos { +#define RUNTIME_INFO_TYPE(V) \ + V(AOT) \ + V(OTHERS) \ + V(NONE) \ + V(JIT) \ + V(JS) \ + V(AOT_BUILD) \ + +enum class RuntimeInfoType { + AOT, + JIT, + OTHERS, + NONE, + JS, + AOT_BUILD, +}; +class AotRuntimeInfo { +public: + constexpr static const int USEC_PER_SEC = 1000 * 1000; + constexpr static const int NSEC_PER_USEC = 1000; + constexpr static const int NT_GNU_BUILD_ID = 3; + constexpr static const int CRASH_INFO_SIZE = 3; + + uint64_t GetMicrosecondsTimeStamp() const + { + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + return time.tv_sec * USEC_PER_SEC + time.tv_nsec / NSEC_PER_USEC; + } + + std::string BuildSingleInfo(const std::string &buildId, const std::string ×tamp, const std::string &type) const + { + return buildId + OhosConstants::SPLIT_STR + timestamp + OhosConstants::SPLIT_STR + type; + } + + std::vector GetCrashRuntimeInfoList(const std::string &soBuildId) const + { + std::string realOutPath = GetCrashSandBoxRealPath(); + std::vector list; + if (realOutPath == "") { + LOG_ECMA(INFO) << "Get crash sanbox path fail."; + return list; + } + list = GetRuntimeInfoByPath(realOutPath, soBuildId); + return list; + } + + void BuildCompileRuntimeInfo(const std::string &type, const std::string &pgoPath) + { + std::string soBuildId = GetRuntimeBuildId(); + if (soBuildId == "") { + LOG_ECMA(INFO) << "can't get so buildId."; + return; + } + std::string realOutPath; + std::string runtimePgoRealPath = pgoPath + OhosConstants::PATH_SEPARATOR + OhosConstants::AOT_RUNTIME_INFO_NAME; + if (!ecmascript::RealPath(runtimePgoRealPath, realOutPath, false)) { + LOG_ECMA(INFO) << "Build compile pgo path fail."; + return; + } + std::vector lines = GetRuntimeInfoByPath(realOutPath, soBuildId); + uint64_t timestamp = GetMicrosecondsTimeStamp(); + std::string buildLine = BuildSingleInfo(soBuildId, std::to_string(timestamp), type); + lines.emplace_back(buildLine); + SetRuntimeInfo(realOutPath, lines); + } + + void BuildCrashRuntimeInfo(const std::string &type) + { + std::string soBuildId = GetRuntimeBuildId(); + if (soBuildId == "") { + LOG_ECMA(INFO) << "can't get so buildId."; + return; + } + std::vector lines = GetCrashRuntimeInfoList(soBuildId); + uint64_t timestamp = GetMicrosecondsTimeStamp(); + std::string buildLine = BuildSingleInfo(soBuildId, std::to_string(timestamp), type); + lines.emplace_back(buildLine); + std::string realOutPath = GetCrashSandBoxRealPath(); + if (realOutPath == "") { + LOG_ECMA(INFO) << "Get crash sanbox path fail."; + return; + } + SetRuntimeInfo(realOutPath, lines); + } + + int GetCompileCountByType(RuntimeInfoType type) + { + std::map escapeMap = CollectCrashSum(); + if (escapeMap.count(type) == 0) { + return 0; + } + return escapeMap[type]; + } + + std::map CollectCrashSum() + { + std::map escapeMap; + std::string soBuildId = GetRuntimeBuildId(); + if (soBuildId == "") { + LOG_ECMA(INFO) << "can't get so buildId."; + return escapeMap; + } + std::vector lines = GetCrashRuntimeInfoList(soBuildId); + for (const std::string &line: lines) { + std::string type = GetType(line); + RuntimeInfoType runtimeInfoType = GetRuntimeInfoTypeByStr(type); + escapeMap[runtimeInfoType]++; + } + return escapeMap; + } + + std::string GetRuntimeBuildId() + { + std::string realPath; + if (!FileExist(OhosConstants::RUNTIME_SO_PATH)) { + return ""; + } + std::string soPath = panda::os::file::File::GetExtendedFilePath(OhosConstants::RUNTIME_SO_PATH); + if (!ecmascript::RealPath(soPath, realPath, false)) { + return ""; + } + if (!FileExist(realPath.c_str())) { + return ""; + } + fileMap = ecmascript::FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ); + if (fileMap.GetOriginAddr() == nullptr) { + return ""; + } + ecmascript::PagePreRead(fileMap.GetOriginAddr(), fileMap.GetSize()); + return ParseELFSectionsForBuildId(); + } + + static std::string GetRuntimeInfoTypeStr(RuntimeInfoType type) + { + const std::map strMap = { +#define RUNTIME_INFO_TYPE_MAP(name) { RuntimeInfoType::name, #name }, + RUNTIME_INFO_TYPE(RUNTIME_INFO_TYPE_MAP) +#undef RUNTIME_INFO_TYPE_MAP + }; + if (strMap.count(type) > 0) { + return strMap.at(type); + } + return ""; + } + + static RuntimeInfoType GetRuntimeInfoTypeByStr(std::string type) + { + const std::map strMap = { +#define RUNTIME_INFO_TYPE_MAP(name) { #name, RuntimeInfoType::name }, + RUNTIME_INFO_TYPE(RUNTIME_INFO_TYPE_MAP) +#undef RUNTIME_INFO_TYPE_MAP + }; + if (strMap.count(type) > 0) { + return strMap.at(type); + } + return RuntimeInfoType::NONE; + } +private: + + void SetRuntimeInfo(const std::string &realOutPath, std::vector lines) const + { + std::ofstream file(realOutPath.c_str(), std::ofstream::out); + for (const std::string &line: lines) { + file << line << "\n"; + } + file.close(); + } + + std::vector GetRuntimeInfoByPath(const std::string &realOutPath, const std::string &soBuildId) const + { + std::ifstream ifile(realOutPath.c_str()); + std::vector lines; + if (ifile.is_open()) { + std::string iline; + while (ifile >> iline) { + std::string buildId = GetBuildId(iline); + if (buildId != soBuildId) { + continue; + } + lines.emplace_back(iline); + } + ifile.close(); + } + return lines; + } + + std::string GetBuildId(std::string crashInfo) const + { + std::vector splitCrashInfo = base::StringHelper::SplitString(crashInfo, OhosConstants::SPLIT_STR); + if (splitCrashInfo.size() == CRASH_INFO_SIZE) { + return splitCrashInfo[0]; + } + return ""; + } + + std::string GetType(std::string crashInfo) const + { + std::vector splitCrashInfo = base::StringHelper::SplitString(crashInfo, OhosConstants::SPLIT_STR); + if (splitCrashInfo.size() == CRASH_INFO_SIZE) { + return splitCrashInfo[2]; + } + return ""; + } + + std::string GetCrashSandBoxRealPath() const + { + std::string realOutPath; + std::string arkProfilePath = AotCrashInfo::GetSandBoxPath(); + std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(arkProfilePath); + if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) { + return ""; + } + realOutPath = realOutPath + OhosConstants::PATH_SEPARATOR + OhosConstants::AOT_RUNTIME_INFO_NAME; + return realOutPath; + } + + std::string ParseELFSectionsForBuildId() const + { + llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast(fileMap.GetOriginAddr()); + char *addr = reinterpret_cast(ehdr); + llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast(addr + ehdr->e_shoff); + ASSERT(ehdr->e_shstrndx != static_cast(-1)); + llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx]; + int secId = -1; + std::string sectionName = ".note.gnu.build-id"; + for (size_t i = 0; i < ehdr->e_shnum; i++) { + llvm::ELF::Elf64_Word shName = shdr[i].sh_name; + char *curShName = reinterpret_cast(addr) + shName + strdr.sh_offset; + if (sectionName.compare(curShName) == 0) { + secId = static_cast(i); + break; + } + } + if (secId == -1) { + return ""; + } + llvm::ELF::Elf64_Shdr secShdr = shdr[secId]; + uint64_t buildIdOffset = secShdr.sh_offset; + uint64_t buildIdSize = secShdr.sh_size; + llvm::ELF::Elf64_Nhdr *nhdr = reinterpret_cast(addr + buildIdOffset); + char *curShNameForNhdr = reinterpret_cast(addr + buildIdOffset + sizeof(*nhdr)); + if (buildIdSize - sizeof(*nhdr) < nhdr->n_namesz) { + return ""; + } + std::string curShNameStr = curShNameForNhdr; + if (curShNameStr.back() == '\0') { + curShNameStr.resize(curShNameStr.size() - 1); + } + + if (curShNameStr != "GNU" || nhdr->n_type != NT_GNU_BUILD_ID) { + return ""; + } + if ((buildIdSize - sizeof(*nhdr) - AlignValues(nhdr->n_namesz, 4) < nhdr->n_descsz) || nhdr->n_descsz == 0) { + return ""; + } + + char *curShNameValueForNhdr = reinterpret_cast(addr + buildIdOffset + sizeof(*nhdr) + + AlignValues(nhdr->n_namesz, 4)); + std::string curShNameValueForNhdrStr = curShNameValueForNhdr; + return GetReadableBuildId(curShNameValueForNhdrStr); + } + + std::string GetReadableBuildId(std::string &buildIdHex) const + { + if (buildIdHex.empty()) { + return ""; + } + static const char HEXTABLE[] = "0123456789abcdef"; + static const int HEXLENGTH = 16; + static const int HEX_EXPAND_PARAM = 2; + const size_t len = buildIdHex.length(); + std::string buildId(len * HEX_EXPAND_PARAM, '\0'); + + for (size_t i = 0; i < len; i++) { + unsigned int n = buildIdHex[i]; + buildId[i * HEX_EXPAND_PARAM] = HEXTABLE[(n >> 4) % HEXLENGTH]; // 4 : higher 4 bit of uint8 + buildId[i * HEX_EXPAND_PARAM + 1] = HEXTABLE[n % HEXLENGTH]; + } + return buildId; + } + + uint64_t AlignValues(uint64_t val, uint64_t align) const + { + return (val + AlignBytes(align)) & AlignMask(align); + } + + uint64_t AlignMask(uint64_t align) const + { + return ~(static_cast((align) - 1)); + } + + uint64_t AlignBytes(uint64_t align) const + { + return (align) - 1; + } + + ecmascript::MemMap fileMap; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H \ No newline at end of file diff --git a/ecmascript/ohos/enable_aot_list_helper.cpp b/ecmascript/ohos/enable_aot_list_helper.cpp index 177a82554a..5083b2a8ad 100644 --- a/ecmascript/ohos/enable_aot_list_helper.cpp +++ b/ecmascript/ohos/enable_aot_list_helper.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License.P */ + #include "ecmascript/ohos/enable_aot_list_helper.h" namespace panda::ecmascript::ohos { diff --git a/ecmascript/ohos/enable_aot_list_helper.h b/ecmascript/ohos/enable_aot_list_helper.h index d0cdf5991d..02a33d4d9b 100644 --- a/ecmascript/ohos/enable_aot_list_helper.h +++ b/ecmascript/ohos/enable_aot_list_helper.h @@ -22,11 +22,19 @@ #include #include +#include "ohos_constants.h" +#include "ecmascript/base/string_helper.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/platform/file.h" +#include "ecmascript/ohos/aot_runtime_info.h" #include "macros.h" + +#ifdef AOT_ESCAPE_ENABLE +#include "parameters.h" +#endif namespace panda::ecmascript::ohos { class EnableAotListHelper { +constexpr static const char *const AOT_BUILD_COUNT_DISABLE = "ark.aot.build.count.disable"; public: static std::shared_ptr GetInstance() { @@ -102,9 +110,38 @@ public: jitEnableList_.clear(); } + static bool GetAotBuildCountDisable() + { +#ifdef AOT_ESCAPE_ENABLE + return OHOS::system::GetBoolParameter(AOT_BUILD_COUNT_DISABLE, false); +#endif + return false; + } + + void AddEnableListCount(const std::string &pgoPath) const + { + ohos::AotRuntimeInfo aotRuntimeInfo; + aotRuntimeInfo.BuildCompileRuntimeInfo( + ohos::AotRuntimeInfo::GetRuntimeInfoTypeStr(ohos::RuntimeInfoType::AOT_BUILD), pgoPath); + } + + bool IsAotCompileSuccessOnce() const + { + if (GetAotBuildCountDisable()) { + return false; + } + ohos::AotRuntimeInfo aotRuntimeInfo; + int count = aotRuntimeInfo.GetCompileCountByType(ohos::RuntimeInfoType::AOT_BUILD); + if (count > 0) { + return true; + } + return false; + } + private: NO_COPY_SEMANTIC(EnableAotListHelper); NO_MOVE_SEMANTIC(EnableAotListHelper); + static void Trim(std::string &data) { if (data.empty()) { diff --git a/ecmascript/ohos/ohos_constants.h b/ecmascript/ohos/ohos_constants.h new file mode 100644 index 0000000000..0ad45222ef --- /dev/null +++ b/ecmascript/ohos/ohos_constants.h @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_COMPILER_OHOS_CONSTANTS_H +#define ECMASCRIPT_COMPILER_OHOS_CONSTANTS_H + +namespace panda::ecmascript::ohos { +namespace OhosConstants { +constexpr const char* SANDBOX_ARK_PROFILE_PATH = "/data/storage/ark-profile"; +constexpr const char* ARM64 = "arm64"; +constexpr const char* RUNTIME_SO_PATH = "/system/lib64/platformsdk/libark_jsruntime.so"; +constexpr const char* PATH_SEPARATOR = "/"; +constexpr const char* AOT_RUNTIME_INFO_NAME = "aot_runtime_info.log"; +constexpr const char* SPLIT_STR = "|"; +} // namespace OhosConstants +} // namespace panda::ecmascript::ohos +#endif // ECMASCRIPT_COMPILER_OHOS_CONSTANTS_H \ No newline at end of file diff --git a/ecmascript/platform/map.h b/ecmascript/platform/map.h index ec281ce87d..256772becb 100644 --- a/ecmascript/platform/map.h +++ b/ecmascript/platform/map.h @@ -86,7 +86,7 @@ void PUBLIC_API PageUnmap(MemMap it); MemMap PUBLIC_API MachineCodePageMap(size_t size, int prot = PAGE_PROT_NONE, size_t alignment = 0); void PUBLIC_API MachineCodePageUnmap(MemMap it); void PageRelease(void *mem, size_t size); -void PagePreRead(void *mem, size_t size); +void PUBLIC_API PagePreRead(void *mem, size_t size); void PageTag(void *mem, size_t size, PageTagType type, const std::string &spaceName = EMPTY_STRING, const uint32_t threadId = 0); void PageClearTag(void *mem, size_t size); diff --git a/js_runtime_config.gni b/js_runtime_config.gni index 021f9a9dca..0d8ddd2a1a 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -228,6 +228,7 @@ template("libark_jsruntime_common_set") { defines += [ "GET_PARAMETER_FOR_JIT", "JIT_ESCAPE_ENABLE", + "AOT_ESCAPE_ENABLE", ] } diff --git a/libark_jsruntime.map b/libark_jsruntime.map index 9fd97a6b69..da56de3d09 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -269,6 +269,7 @@ panda::ecmascript::PageSize*; panda::ecmascript::PageUnmap*; panda::ecmascript::PageSize*; + panda::ecmascript::PagePreRead*; panda::ecmascript::pgo::PGOProfiler::GetMethodAbcId*; panda::ecmascript::RealPath*; panda::ecmascript::SetDirModeAsDefault*;