mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
!7417 change AOT escape code macros
Merge pull request !7417 from herongpeng/aot_escape_marcros Change-Id: I596cc858805899b3c1db64af34edd1afd98bc2c8
This commit is contained in:
commit
6771b034cd
@ -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");
|
||||
|
@ -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<EntityId, std::string> 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<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;
|
||||
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<struct JsFrameInfo> JsStackInfo::BuildJsStackInfo(JSThread *thread, bool currentStack)
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <csignal>
|
||||
#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<EntityId, std::string> 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(
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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<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()
|
||||
{
|
||||
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)
|
||||
|
@ -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<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()
|
||||
{
|
||||
#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<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
|
||||
#endif // ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H
|
||||
|
330
ecmascript/ohos/aot_runtime_info.h
Normal file
330
ecmascript/ohos/aot_runtime_info.h
Normal 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 ×tamp, 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
|
@ -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 {
|
||||
|
@ -22,11 +22,19 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<EnableAotListHelper> 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()) {
|
||||
|
29
ecmascript/ohos/ohos_constants.h
Normal file
29
ecmascript/ohos/ohos_constants.h
Normal 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
|
@ -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);
|
||||
|
@ -228,6 +228,7 @@ template("libark_jsruntime_common_set") {
|
||||
defines += [
|
||||
"GET_PARAMETER_FOR_JIT",
|
||||
"JIT_ESCAPE_ENABLE",
|
||||
"AOT_ESCAPE_ENABLE",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -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*;
|
||||
|
Loading…
Reference in New Issue
Block a user