!7417 change AOT escape code macros

Merge pull request !7417 from herongpeng/aot_escape_marcros

Change-Id: I596cc858805899b3c1db64af34edd1afd98bc2c8
This commit is contained in:
openharmony_ci 2024-05-18 02:07:27 +00:00 committed by h30044958
commit 6771b034cd
13 changed files with 430 additions and 269 deletions

View File

@ -28,6 +28,7 @@
#include "ecmascript/log.h" #include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h" #include "ecmascript/log_wrapper.h"
#include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/napi/include/jsnapi.h"
#include "ecmascript/ohos/enable_aot_list_helper.h"
#include "ecmascript/ohos/ohos_pkg_args.h" #include "ecmascript/ohos/ohos_pkg_args.h"
#include "ecmascript/platform/file.h" #include "ecmascript/platform/file.h"
#include "ecmascript/platform/os.h" #include "ecmascript/platform/os.h"
@ -220,6 +221,7 @@ int Main(const int argc, const char **argv)
if (runtimeOptions.IsTargetCompilerMode()) { if (runtimeOptions.IsTargetCompilerMode()) {
compilerStats.PrintCompilerStatsLog(); compilerStats.PrintCompilerStatsLog();
} }
ohos::EnableAotListHelper::GetInstance()->AddEnableListCount(cPreprocessor.GetMainPkgArgs()->GetPgoDir());
} }
LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed"); LOG_COMPILER(INFO) << (ret ? "ts aot compile success" : "ts aot compile failed");

View File

@ -24,6 +24,7 @@
#include "ecmascript/jspandafile/program_object.h" #include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/mem/heap-inl.h" #include "ecmascript/mem/heap-inl.h"
#include "ecmascript/message_string.h" #include "ecmascript/message_string.h"
#include "ecmascript/ohos/aot_runtime_info.h"
#include "ecmascript/platform/os.h" #include "ecmascript/platform/os.h"
#if defined(PANDA_TARGET_OHOS) #if defined(PANDA_TARGET_OHOS)
#include "ecmascript/extractortool/src/extractor.h" #include "ecmascript/extractortool/src/extractor.h"
@ -34,10 +35,6 @@
namespace panda::ecmascript { namespace panda::ecmascript {
[[maybe_unused]] static bool g_needCheck = true; [[maybe_unused]] static bool g_needCheck = true;
const int USEC_PER_SEC = 1000 * 1000;
const int NSEC_PER_USEC = 1000;
std::unordered_map<EntityId, std::string> JsStackInfo::nameMap; std::unordered_map<EntityId, std::string> JsStackInfo::nameMap;
std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile) 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; 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) void JsStackInfo::BuildCrashInfo(bool isJsCrash, uintptr_t pc)
{ {
if (JsStackInfo::loader != nullptr && !JsStackInfo::loader->IsEnableAOT() && if (JsStackInfo::loader != nullptr && !JsStackInfo::loader->IsEnableAOT() &&
JsStackInfo::options != nullptr && !JsStackInfo::options->IsEnableJIT()) { JsStackInfo::options != nullptr && !JsStackInfo::options->IsEnableJIT()) {
return; return;
} }
std::string realOutPath; ohos::RuntimeInfoType type;
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<std::string> 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;
if (isJsCrash) { if (isJsCrash) {
type = ohos::CrashType::JS; type = ohos::RuntimeInfoType::JS;
} else if (pc != 0 && JsStackInfo::loader != nullptr && JsStackInfo::loader->InsideAOT(pc)) { } else if (pc != 0 && JsStackInfo::loader != nullptr && JsStackInfo::loader->InsideAOT(pc)) {
type = ohos::CrashType::AOT; type = ohos::RuntimeInfoType::AOT;
} else { } else {
type = ohos::CrashType::OTHERS; type = ohos::RuntimeInfoType::OTHERS;
} }
std::string buildLine = ohos::AotCrashInfo::BuildAotCrashInfo(soBuildId, std::to_string(timestamp), type); ohos::AotRuntimeInfo aotRuntimeInfo;
lines.emplace_back(buildLine); aotRuntimeInfo.BuildCrashRuntimeInfo(ohos::AotRuntimeInfo::GetRuntimeInfoTypeStr(type));
std::ofstream file(realOutPath.c_str(), std::ofstream::out);
for (const std::string& line : lines) {
file << line << "\n";
}
file.close();
} }
std::vector<struct JsFrameInfo> JsStackInfo::BuildJsStackInfo(JSThread *thread, bool currentStack) std::vector<struct JsFrameInfo> JsStackInfo::BuildJsStackInfo(JSThread *thread, bool currentStack)

View File

@ -19,7 +19,6 @@
#include <csignal> #include <csignal>
#include "ecmascript/compiler/aot_file/aot_file_manager.h" #include "ecmascript/compiler/aot_file/aot_file_manager.h"
#include "ecmascript/extractortool/src/source_map.h" #include "ecmascript/extractortool/src/source_map.h"
#include "ecmascript/ohos/aot_crash_info.h"
#include "ecmascript/js_thread.h" #include "ecmascript/js_thread.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h" #include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/dfx/dump_code/jit_dump_elf.h" #include "ecmascript/dfx/dump_code/jit_dump_elf.h"
@ -165,7 +164,6 @@ public:
static std::unordered_map<EntityId, std::string> nameMap; static std::unordered_map<EntityId, std::string> nameMap;
}; };
void CrashCallback(char *buf, size_t len, void *ucontext); void CrashCallback(char *buf, size_t len, void *ucontext);
uint64_t GetMicrosecondsTimeStamp();
} // namespace panda::ecmascript } // namespace panda::ecmascript
#endif // ECMASCRIPT_DFX_STACKINFO_JS_STACKINFO_H #endif // ECMASCRIPT_DFX_STACKINFO_JS_STACKINFO_H
extern "C" int step_ark_managed_native_frame( extern "C" int step_ark_managed_native_frame(

View File

@ -231,8 +231,13 @@ void EcmaVM::PostFork()
} else if (ohos::EnableAotListHelper::GetInstance()->IsEnableList(bundleName)) { } else if (ohos::EnableAotListHelper::GetInstance()->IsEnableList(bundleName)) {
options_.SetEnablePGOProfiler(true); options_.SetEnablePGOProfiler(true);
} }
if (ohos::EnableAotListHelper::GetInstance()->IsAotCompileSuccessOnce()) {
options_.SetEnablePGOProfiler(false);
LOG_ECMA(INFO) << "Aot has compile success once.";
}
if (JSNApi::IsAotEscape()) { if (JSNApi::IsAotEscape()) {
options_.SetEnablePGOProfiler(false); options_.SetEnablePGOProfiler(false);
LOG_ECMA(INFO) << "Aot has escaped.";
} }
ResetPGOProfiler(); ResetPGOProfiler();

View File

@ -93,6 +93,7 @@
#include "ecmascript/js_weak_container.h" #include "ecmascript/js_weak_container.h"
#include "ecmascript/ohos/aot_crash_info.h" #include "ecmascript/ohos/aot_crash_info.h"
#include "ecmascript/ohos/framework_helper.h" #include "ecmascript/ohos/framework_helper.h"
#include "ecmascript/ohos/aot_runtime_info.h"
#ifdef ARK_SUPPORT_INTL #ifdef ARK_SUPPORT_INTL
#include "ecmascript/js_bigint.h" #include "ecmascript/js_bigint.h"
#include "ecmascript/js_collator.h" #include "ecmascript/js_collator.h"
@ -199,7 +200,6 @@ using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager;
using FrameIterator = ecmascript::FrameIterator; using FrameIterator = ecmascript::FrameIterator;
using Concurrent = ecmascript::Concurrent; using Concurrent = ecmascript::Concurrent;
using CrashInfo = ecmascript::ohos::AotCrashInfo; using CrashInfo = ecmascript::ohos::AotCrashInfo;
using CrashType = ecmascript::ohos::CrashType;
namespace { namespace {
// NOLINTNEXTLINE(fuchsia-statically-constructed-objects) // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
@ -4268,51 +4268,26 @@ bool JSNApi::KeyIsNumber(const char* utf8)
return true; return true;
} }
std::map<CrashType, int> CollectCrashSum()
{
std::map<CrashType, int> 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() bool JSNApi::IsAotEscape()
{ {
if (CrashInfo::GetAotEscapeDisable()) { if (CrashInfo::GetAotEscapeDisable()) {
return false; return false;
} }
auto escapeMap = CollectCrashSum(); ecmascript::ohos::AotRuntimeInfo aotRuntimeInfo;
return escapeMap[CrashType::AOT] >= CrashInfo::GetAotCrashCount() || auto escapeMap = aotRuntimeInfo.CollectCrashSum();
escapeMap[CrashType::OTHERS] >= CrashInfo::GetOthersCrashCount() || return escapeMap[ecmascript::ohos::RuntimeInfoType::AOT] >= CrashInfo::GetAotCrashCount() ||
escapeMap[CrashType::JS] >= CrashInfo::GetJsCrashCount(); escapeMap[ecmascript::ohos::RuntimeInfoType::OTHERS] >= CrashInfo::GetOthersCrashCount() ||
escapeMap[ecmascript::ohos::RuntimeInfoType::JS] >= CrashInfo::GetJsCrashCount();
} }
bool JSNApi::IsJitEscape() bool JSNApi::IsJitEscape()
{ {
auto escapeMap = CollectCrashSum(); ecmascript::ohos::AotRuntimeInfo aotRuntimeInfo;
return escapeMap[CrashType::JIT] >= CrashInfo::GetJitCrashCount() || auto escapeMap = aotRuntimeInfo.CollectCrashSum();
escapeMap[CrashType::AOT] >= CrashInfo::GetAotCrashCount() || return escapeMap[ecmascript::ohos::RuntimeInfoType::JIT] >= CrashInfo::GetJitCrashCount() ||
escapeMap[CrashType::OTHERS] >= CrashInfo::GetOthersCrashCount() || escapeMap[ecmascript::ohos::RuntimeInfoType::AOT] >= CrashInfo::GetAotCrashCount() ||
escapeMap[CrashType::JS] >= CrashInfo::GetJsCrashCount(); escapeMap[ecmascript::ohos::RuntimeInfoType::OTHERS] >= CrashInfo::GetOthersCrashCount() ||
escapeMap[ecmascript::ohos::RuntimeInfoType::JS] >= CrashInfo::GetJsCrashCount();
} }
bool JSNApi::IsSerializationTimeoutCheckEnabled(const EcmaVM *vm) bool JSNApi::IsSerializationTimeoutCheckEnabled(const EcmaVM *vm)

View File

@ -16,36 +16,20 @@
#ifndef ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H #ifndef ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H
#define 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" #include "ecmascript/base/string_helper.h"
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) #ifdef AOT_ESCAPE_ENABLE
#include "parameters.h" #include "parameters.h"
#endif #endif
namespace panda::ecmascript::ohos { 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 { 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 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 SPLIT_STR = "|";
constexpr static const char *const AOT_ESCAPE_DISABLE = "ark.aot.escape.disable"; constexpr static const char *const AOT_ESCAPE_DISABLE = "ark.aot.escape.disable";
constexpr static int AOT_CRASH_COUNT = 1; constexpr static int AOT_CRASH_COUNT = 1;
constexpr static int OTHERS_CRASH_COUNT = 3; constexpr static int OTHERS_CRASH_COUNT = 3;
constexpr static int CRASH_LOG_SIZE = 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 JIT_CRASH_COUNT = 1;
constexpr static int JS_CRASH_COUNT = 3; constexpr static int JS_CRASH_COUNT = 3;
public: public:
@ -53,26 +37,9 @@ public:
explicit AotCrashInfo() = default; explicit AotCrashInfo() = default;
virtual ~AotCrashInfo() = default; virtual ~AotCrashInfo() = default;
static CrashType GetCrashType(std::string crashInfo)
{
std::vector<std::string> 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() static bool GetAotEscapeDisable()
{ {
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) #ifdef AOT_ESCAPE_ENABLE
return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false); return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false);
#endif #endif
return false; return false;
@ -80,7 +47,7 @@ public:
static std::string GetSandBoxPath() static std::string GetSandBoxPath()
{ {
return SANDBOX_ARK_PROFILE_PATH; return OhosConstants::SANDBOX_ARK_PROFILE_PATH;
} }
static std::string GetCrashFileName() static std::string GetCrashFileName()
@ -107,150 +74,6 @@ public:
{ {
return OTHERS_CRASH_COUNT; return OTHERS_CRASH_COUNT;
} }
static std::string GetCrashTypeStr(CrashType type)
{
const std::map<CrashType, const char *> 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<std::string, CrashType> 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<std::string> 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<uint64_t>((align) - 1));
}
uint64_t AlignBytes(uint64_t align)
{
return (align) - 1;
}
std::string ParseELFSectionsForBuildId()
{
llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMap.GetOriginAddr());
char *addr = reinterpret_cast<char *>(ehdr);
llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff);
ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-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<char *>(addr) + shName + strdr.sh_offset;
if (sectionName.compare(curShName) == 0) {
secId = static_cast<int>(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<llvm::ELF::Elf64_Nhdr *>(addr + buildIdOffset);
char *curShNameForNhdr = reinterpret_cast<char *>(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<char *>(addr + buildIdOffset + sizeof(*nhdr)
+ AlignValues(nhdr->n_namesz, 4));
std::string curShNameValueForNhdrStr = curShNameValueForNhdr;
return GetReadableBuildId(curShNameValueForNhdrStr);
}
ecmascript::MemMap fileMap;
}; };
} // namespace panda::ecmascript } // namespace panda::ecmascript
#endif // ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H #endif // ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H

View File

@ -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 <sys/time.h>
#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 &timestamp, const std::string &type) const
{
return buildId + OhosConstants::SPLIT_STR + timestamp + OhosConstants::SPLIT_STR + type;
}
std::vector<std::string> GetCrashRuntimeInfoList(const std::string &soBuildId) const
{
std::string realOutPath = GetCrashSandBoxRealPath();
std::vector<std::string> 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<std::string> 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<std::string> 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<RuntimeInfoType, int> escapeMap = CollectCrashSum();
if (escapeMap.count(type) == 0) {
return 0;
}
return escapeMap[type];
}
std::map<RuntimeInfoType, int> CollectCrashSum()
{
std::map<RuntimeInfoType, int> escapeMap;
std::string soBuildId = GetRuntimeBuildId();
if (soBuildId == "") {
LOG_ECMA(INFO) << "can't get so buildId.";
return escapeMap;
}
std::vector<std::string> 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<RuntimeInfoType, const char *> 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<std::string, RuntimeInfoType> 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<std::string> lines) const
{
std::ofstream file(realOutPath.c_str(), std::ofstream::out);
for (const std::string &line: lines) {
file << line << "\n";
}
file.close();
}
std::vector<std::string> GetRuntimeInfoByPath(const std::string &realOutPath, const std::string &soBuildId) const
{
std::ifstream ifile(realOutPath.c_str());
std::vector<std::string> 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<std::string> 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<std::string> 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<llvm::ELF::Elf64_Ehdr *>(fileMap.GetOriginAddr());
char *addr = reinterpret_cast<char *>(ehdr);
llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff);
ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-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<char *>(addr) + shName + strdr.sh_offset;
if (sectionName.compare(curShName) == 0) {
secId = static_cast<int>(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<llvm::ELF::Elf64_Nhdr *>(addr + buildIdOffset);
char *curShNameForNhdr = reinterpret_cast<char *>(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<char *>(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<uint64_t>((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

View File

@ -12,6 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License.P * limitations under the License.P
*/ */
#include "ecmascript/ohos/enable_aot_list_helper.h" #include "ecmascript/ohos/enable_aot_list_helper.h"
namespace panda::ecmascript::ohos { namespace panda::ecmascript::ohos {

View File

@ -22,11 +22,19 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "ohos_constants.h"
#include "ecmascript/base/string_helper.h"
#include "ecmascript/log_wrapper.h" #include "ecmascript/log_wrapper.h"
#include "ecmascript/platform/file.h" #include "ecmascript/platform/file.h"
#include "ecmascript/ohos/aot_runtime_info.h"
#include "macros.h" #include "macros.h"
#ifdef AOT_ESCAPE_ENABLE
#include "parameters.h"
#endif
namespace panda::ecmascript::ohos { namespace panda::ecmascript::ohos {
class EnableAotListHelper { class EnableAotListHelper {
constexpr static const char *const AOT_BUILD_COUNT_DISABLE = "ark.aot.build.count.disable";
public: public:
static std::shared_ptr<EnableAotListHelper> GetInstance() static std::shared_ptr<EnableAotListHelper> GetInstance()
{ {
@ -102,9 +110,38 @@ public:
jitEnableList_.clear(); 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: private:
NO_COPY_SEMANTIC(EnableAotListHelper); NO_COPY_SEMANTIC(EnableAotListHelper);
NO_MOVE_SEMANTIC(EnableAotListHelper); NO_MOVE_SEMANTIC(EnableAotListHelper);
static void Trim(std::string &data) static void Trim(std::string &data)
{ {
if (data.empty()) { if (data.empty()) {

View File

@ -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

View File

@ -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); MemMap PUBLIC_API MachineCodePageMap(size_t size, int prot = PAGE_PROT_NONE, size_t alignment = 0);
void PUBLIC_API MachineCodePageUnmap(MemMap it); void PUBLIC_API MachineCodePageUnmap(MemMap it);
void PageRelease(void *mem, size_t size); 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, void PageTag(void *mem, size_t size, PageTagType type, const std::string &spaceName = EMPTY_STRING,
const uint32_t threadId = 0); const uint32_t threadId = 0);
void PageClearTag(void *mem, size_t size); void PageClearTag(void *mem, size_t size);

View File

@ -228,6 +228,7 @@ template("libark_jsruntime_common_set") {
defines += [ defines += [
"GET_PARAMETER_FOR_JIT", "GET_PARAMETER_FOR_JIT",
"JIT_ESCAPE_ENABLE", "JIT_ESCAPE_ENABLE",
"AOT_ESCAPE_ENABLE",
] ]
} }

View File

@ -269,6 +269,7 @@
panda::ecmascript::PageSize*; panda::ecmascript::PageSize*;
panda::ecmascript::PageUnmap*; panda::ecmascript::PageUnmap*;
panda::ecmascript::PageSize*; panda::ecmascript::PageSize*;
panda::ecmascript::PagePreRead*;
panda::ecmascript::pgo::PGOProfiler::GetMethodAbcId*; panda::ecmascript::pgo::PGOProfiler::GetMethodAbcId*;
panda::ecmascript::RealPath*; panda::ecmascript::RealPath*;
panda::ecmascript::SetDirModeAsDefault*; panda::ecmascript::SetDirModeAsDefault*;