From 457d54d616171de39191c6ad76101a16f80ca328 Mon Sep 17 00:00:00 2001 From: binaryfz Date: Tue, 29 Dec 2020 14:17:27 +0800 Subject: [PATCH] add maple_util sourcecode --- src/mapleall/maple_util/src/error_code.cpp | 48 ++ src/mapleall/maple_util/src/file_layout.cpp | 39 ++ src/mapleall/maple_util/src/itab_util.cpp | 47 ++ .../maple_util/src/literalstrname.cpp | 65 ++ src/mapleall/maple_util/src/mpl_logging.cpp | 174 +++++ src/mapleall/maple_util/src/mpl_scheduler.cpp | 241 +++++++ src/mapleall/maple_util/src/mpl_timer.cpp | 42 ++ src/mapleall/maple_util/src/muid.cpp | 305 +++++++++ src/mapleall/maple_util/src/namemangler.cpp | 626 ++++++++++++++++++ src/mapleall/maple_util/src/string_utils.cpp | 73 ++ src/mapleall/maple_util/src/thread_env.cpp | 19 + 11 files changed, 1679 insertions(+) create mode 100644 src/mapleall/maple_util/src/error_code.cpp create mode 100644 src/mapleall/maple_util/src/file_layout.cpp create mode 100644 src/mapleall/maple_util/src/itab_util.cpp create mode 100644 src/mapleall/maple_util/src/literalstrname.cpp create mode 100644 src/mapleall/maple_util/src/mpl_logging.cpp create mode 100644 src/mapleall/maple_util/src/mpl_scheduler.cpp create mode 100644 src/mapleall/maple_util/src/mpl_timer.cpp create mode 100644 src/mapleall/maple_util/src/muid.cpp create mode 100644 src/mapleall/maple_util/src/namemangler.cpp create mode 100644 src/mapleall/maple_util/src/string_utils.cpp create mode 100644 src/mapleall/maple_util/src/thread_env.cpp diff --git a/src/mapleall/maple_util/src/error_code.cpp b/src/mapleall/maple_util/src/error_code.cpp new file mode 100644 index 0000000000..9295313a3b --- /dev/null +++ b/src/mapleall/maple_util/src/error_code.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include + +namespace maple { +void PrintErrorMessage(int ret) { + switch (ret) { + case kErrorNoError: + case kErrorExitHelp: + break; + case kErrorExit: + ERR(kLncErr, "Error Exit!"); + break; + case kErrorInvalidParameter: + ERR(kLncErr, "Invalid Parameter!"); + break; + case kErrorInitFail: + ERR(kLncErr, "Init Fail!"); + break; + case kErrorFileNotFound: + ERR(kLncErr, "File Not Found!"); + break; + case kErrorToolNotFound: + ERR(kLncErr, "Tool Not Found!"); + break; + case kErrorCompileFail: + ERR(kLncErr, "Compile Fail!"); + break; + case kErrorNotImplement: + ERR(kLncErr, "Not Implement!"); + break; + default: + break; + } +} +} // namespace maple diff --git a/src/mapleall/maple_util/src/file_layout.cpp b/src/mapleall/maple_util/src/file_layout.cpp new file mode 100644 index 0000000000..980b104720 --- /dev/null +++ b/src/mapleall/maple_util/src/file_layout.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "file_layout.h" + +namespace maple { +std::string GetLayoutTypeString(uint32_t type) { + switch (type) { + case kLayoutBootHot: + return "BootHot"; + case kLayoutBothHot: + return "BothHot"; + case kLayoutRunHot: + return "RunHot"; + case kLayoutStartupOnly: + return "StartupOnly"; + case kLayoutUsedOnce: + return "UsedOnce"; + case kLayoutExecuted: + return "UsedMaybe"; + case kLayoutUnused: + return "Unused"; + default: + std::cerr << "no such type" << std::endl; + return ""; + } +} +} // namespace maple diff --git a/src/mapleall/maple_util/src/itab_util.cpp b/src/mapleall/maple_util/src/itab_util.cpp new file mode 100644 index 0000000000..4cb0969a41 --- /dev/null +++ b/src/mapleall/maple_util/src/itab_util.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "itab_util.h" +#include +#include +#include + +namespace maple { +unsigned int DJBHash(const char *str) { + unsigned int hash = 5381; // initial value for DJB hash algorithm + while (*str) { + hash += (hash << 5) + (unsigned char)(*str++); // calculate the hash code of data + } + return (hash & 0x7FFFFFFF); +} + +unsigned int GetHashIndex(const char *name) { + unsigned int hashcode = DJBHash(name); + return (hashcode % kHashSize); +} + +struct CmpStr { + bool operator()(char const *a, char const *b) const { + return std::strcmp(a, b) < 0; + } +}; + +std::mutex mapLock; + +unsigned int GetSecondHashIndex(const char *name) { + std::lock_guard guard(mapLock); + unsigned int hashcode = DJBHash(name); + return hashcode % kItabSecondHashSize; +} +} // namespace maple diff --git a/src/mapleall/maple_util/src/literalstrname.cpp b/src/mapleall/maple_util/src/literalstrname.cpp new file mode 100644 index 0000000000..504e1dc1dd --- /dev/null +++ b/src/mapleall/maple_util/src/literalstrname.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "literalstrname.h" + +// literal string name is shared between maple compiler and runtime, thus not in namespace maplert +// note there is a macor kConstString "_C_STR_" in literalstrname.h +// which need to match +static std::string mplConstStr("_C_STR_00000000000000000000000000000000"); +const uint32_t kMaxBytesLength = 15; + +namespace { +const char *kMplDigits = "0123456789abcdef"; +} + +// Return the hex string of bytes. The result is the combination of prefix "_C_STR_" and hex string of bytes. +// The upper 4 bits and lower 4 bits of bytes[i] are transformed to hex form and restored separately in hex string. +std::string LiteralStrName::GetHexStr(const uint8_t *bytes, uint32_t len) { + if (bytes == nullptr) { + return std::string(); + } + std::string str(mplConstStr, 0, (len << 1) + kConstStringLen); + for (unsigned i = 0; i < len; ++i) { + str[2 * i + kConstStringLen] = kMplDigits[(bytes[i] & 0xf0) >> 4]; // get the hex value of upper 4 bits of bytes[i] + str[2 * i + kConstStringLen + 1] = kMplDigits[bytes[i] & 0x0f]; // get the hex value of lower 4 bits of bytes[i] + } + return str; +} + +// Return the hash code of data. The hash code is computed as +// s[0] * 31 ^ (len - 1) + s[1] * 31 ^ (len - 2) + ... + s[len - 1], +// where s[i] is the value of swapping the upper 8 bits and lower 8 bits of data[i]. +int32_t LiteralStrName::CalculateHashSwapByte(const char16_t *data, uint32_t len) { + uint32_t hash = 0; + const char16_t *end = data + len; + while (data < end) { + hash = (hash << 5) - hash; + char16_t val = *data++; + hash += (((val << 8) & 0xff00) | ((val >> 8) & 0xff)); + } + return static_cast(hash); +} + +std::string LiteralStrName::GetLiteralStrName(const uint8_t *bytes, uint32_t len) { + if (len <= kMaxBytesLength) { + return GetHexStr(bytes, len); + } + return ComputeMuid(bytes, len); +} + +std::string LiteralStrName::ComputeMuid(const uint8_t *bytes, uint32_t len) { + DigestHash digestHash = GetDigestHash(*bytes, len); + return GetHexStr(digestHash.bytes, kDigestHashLength); +} \ No newline at end of file diff --git a/src/mapleall/maple_util/src/mpl_logging.cpp b/src/mapleall/maple_util/src/mpl_logging.cpp new file mode 100644 index 0000000000..9defdfe914 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_logging.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "mpl_logging.h" +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include "securec.h" + +namespace { +constexpr uint32_t kMaxLogLen = 10000; +} + +namespace maple { +LogInfo logInfo; +LogInfo &log = logInfo; + +const char *kLongLogLevels[] = { [kLlDbg] = "D", [kLlLog] = "L", [kLlInfo] = "Info ", + [kLlWarn] = "Warn ", [kLlErr] = "Error", [kLlFatal] = "Fatal" }; + +const char *tags[] = { + [kLtThread] = "TR", + [kLtLooper] = "LP", +}; + +SECUREC_ATTRIBUTE(7, 8) void LogInfo::EmitLogForDevelop(enum LogTags tag, enum LogLevel ll, const std::string &file, + const std::string &func, int line, const char *fmt, ...) { + char buf[kMaxLogLen]; + ASSERT(tag < kLtAll, "illegal log tag"); + +#ifndef _WIN32 + pid_t tid = syscall(SYS_gettid); +#endif + + time_t timeSeconds = time(nullptr); + struct tm *nowTime = localtime(&timeSeconds); + CHECK_FATAL(nowTime != nullptr, "(nowTime) null ptr check"); + int month = nowTime->tm_mon + 1; + int day = nowTime->tm_mday; + int hour = nowTime->tm_hour; + int min = nowTime->tm_min; + int sec = nowTime->tm_sec; + +#ifdef _WIN32 + int lenFront = snprintf_s(buf, kMaxLogLen, kMaxLogLen - 1, "%02d-%02d %02d:%02d:%02d %s %s ", + month, day, hour, min, sec, tags[tag], kLongLogLevels[ll]); +#else + int lenFront = snprintf_s(buf, kMaxLogLen, kMaxLogLen - 1, "%02d-%02d %02d:%02d:%02d %s %d %s ", + month, day, hour, min, sec, tags[tag], tid, kLongLogLevels[ll]); +#endif + + if (lenFront == -1) { + WARN(kLncWarn, "snprintf_s failed in mpl_logging.cpp"); + return; + } + va_list l; + va_start(l, fmt); + + int lenBack = vsnprintf_s(buf + lenFront, kMaxLogLen - lenFront, + static_cast(kMaxLogLen - lenFront - 1), fmt, l); + if (lenBack == -1) { + WARN(kLncWarn, "vsnprintf_s failed "); + va_end(l); + return; + } + if (outMode != 0) { + int eNum = snprintf_s(buf + lenFront + lenBack, kMaxLogLen - lenFront - lenBack, + kMaxLogLen - lenFront - lenBack - 1, " [%s] [%s:%d]", func.c_str(), file.c_str(), line); + if (eNum == -1) { + WARN(kLncWarn, "snprintf_s failed"); + va_end(l); + return; + } + } else { + int eNum = snprintf_s(buf + lenFront + lenBack, kMaxLogLen - lenFront - lenBack, + kMaxLogLen - lenFront - lenBack - 1, " [%s]", func.c_str()); + if (eNum == -1) { + WARN(kLncWarn, "snprintf_s failed"); + va_end(l); + return; + } + } + va_end(l); + fprintf(outStream, "%s\n", buf); + return; +} + +SECUREC_ATTRIBUTE(4, 5) void LogInfo::EmitLogForUser(enum LogNumberCode num, enum LogLevel ll, const char *fmt, + ...) const { + char buf[kMaxLogLen]; + int len = snprintf_s(buf, kMaxLogLen, kMaxLogLen - 1, "%s %02d: ", kLongLogLevels[ll], num); + if (len == -1) { + WARN(kLncWarn, "snprintf_s failed"); + return; + } + if (outMode) { + va_list l; + va_start(l, fmt); + int eNum = vsnprintf_s(buf + len, kMaxLogLen - len, static_cast(kMaxLogLen - len - 1), fmt, l); + if (eNum == -1) { + WARN(kLncWarn, "vsnprintf_s failed"); + va_end(l); + return; + } + va_end(l); + } + std::cerr << buf << '\n'; + return; +} + +void LogInfo::EmitLogForUser(enum LogNumberCode num, enum LogLevel ll, const std::string &message) const { + EmitLogForUser(num, ll, "%s", message.c_str()); +} + +SECUREC_ATTRIBUTE(5, 6) void LogInfo::EmitErrorMessage(const std::string &cond, const std::string &file, + unsigned int line, const char *fmt, ...) const { + char buf[kMaxLogLen]; +#ifdef _WIN32 + int len = snprintf_s(buf, kMaxLogLen, kMaxLogLen - 1, "CHECK/CHECK_FATAL failure: %s at [%s:%d] ", + cond.c_str(), file.c_str(), line); +#else + pid_t tid = syscall(SYS_gettid); + int len = snprintf_s(buf, kMaxLogLen, kMaxLogLen - 1, "Tid(%d): CHECK/CHECK_FATAL failure: %s at [%s:%d] ", + tid, cond.c_str(), file.c_str(), line); +#endif + if (len == -1) { + WARN(kLncWarn, "snprintf_s failed"); + return; + } + va_list l; + va_start(l, fmt); + int eNum = vsnprintf_s(buf + len, kMaxLogLen - len, static_cast(kMaxLogLen - len - 1), fmt, l); + if (eNum == -1) { + WARN(kLncWarn, "vsnprintf_s failed"); + va_end(l); + return; + } + va_end(l); + std::cerr << buf; +} + +std::ios::fmtflags LogInfo::Flags() { + std::ios::fmtflags flag(std::cout.flags()); + return std::cout.flags(flag); +} + +std::ostream &LogInfo::MapleLogger(LogLevel level) { + if (level == kLlLog) { + return std::cout; + } else { + return std::cerr; + } +} +std::ostream &LogInfo::Info() { + return std::cout; +} +std::ostream &LogInfo::Err() { + return std::cerr; +} +} // namespace maple diff --git a/src/mapleall/maple_util/src/mpl_scheduler.cpp b/src/mapleall/maple_util/src/mpl_scheduler.cpp new file mode 100644 index 0000000000..402054c470 --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_scheduler.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "mpl_scheduler.h" +#include "mpl_timer.h" +#include "mpl_logging.h" +namespace maple { +constexpr double kAlternateUnits = 1000.0; +// ========== MplScheduler ========== +MplScheduler::MplScheduler(const std::string &name) + : schedulerName(name), + taskIdForAdd(0), + taskIdToRun(0), + taskIdExpected(0), + numberTasks(0), + numberTasksFinish(0), + isSchedulerSeq(false), + dumpTime(false), + statusFinish(kThreadRun) {} + +void MplScheduler::Init() { + char *envStr = getenv("MP_DUMPTIME"); + if (envStr != nullptr && atoi(envStr) == 1) { + dumpTime = true; + } + int ret = pthread_mutex_init(&mutexTaskIdsToRun, nullptr); + CHECK_FATAL(ret == 0, "pthread_mutex_init failed"); + ret = pthread_mutex_init(&mutexTaskIdsToFinish, nullptr); + CHECK_FATAL(ret == 0, "pthread_mutex_init failed"); + ret = pthread_mutex_init(&mutexGlobal, nullptr); + CHECK_FATAL(ret == 0, "pthread_mutex_init failed"); + mutexTaskFinishProcess = PTHREAD_MUTEX_INITIALIZER; + conditionFinishProcess = PTHREAD_COND_INITIALIZER; +} + +void MplScheduler::AddTask(MplTask *task) { + task->SetTaskId(taskIdForAdd); + tbTasks.push_back(task); + ++taskIdForAdd; + ++numberTasks; +} + +MplTask *MplScheduler::GetTaskToRun() { + MplTask *task = nullptr; + int ret = pthread_mutex_lock(&mutexTaskIdsToRun); + CHECK_FATAL(ret == 0, "pthread_mutex_lock failed"); + if (taskIdToRun < numberTasks) { + task = tbTasks[taskIdToRun++]; + } + ret = pthread_mutex_unlock(&mutexTaskIdsToRun); + CHECK_FATAL(ret == 0, "pthread_mutex_unlock failed"); + return task; +} + +size_t MplScheduler::GetTaskIdsFinishSize() { + int ret = pthread_mutex_lock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_lock failed"); + size_t size = tbTaskIdsToFinish.size(); + ret = pthread_mutex_unlock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_unlock failed"); + return size; +} + +MplTask *MplScheduler::GetTaskFinishFirst() { + MplTask *task = nullptr; + int ret = pthread_mutex_lock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_lock failed"); + if (!tbTaskIdsToFinish.empty()) { + task = tbTasks[*(tbTaskIdsToFinish.begin())]; + } + ret = pthread_mutex_unlock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_unlock failed"); + return task; +} + +void MplScheduler::RemoveTaskFinish(uint32 id) { + int ret = pthread_mutex_lock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_lock failed"); + tbTaskIdsToFinish.erase(id); + ret = pthread_mutex_unlock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_unlock failed"); +} + +void MplScheduler::TaskIdFinish(uint32 id) { + int ret = pthread_mutex_lock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_lock failed"); + tbTaskIdsToFinish.insert(id); + ret = pthread_mutex_unlock(&mutexTaskIdsToFinish); + CHECK_FATAL(ret == 0, "pthread_mutex_unlock failed"); +} + +int MplScheduler::RunTask(uint32 threadsNum, bool seq) { + isSchedulerSeq = seq; + if (threadsNum > 0) { + taskIdExpected = 0; + std::thread threads[threadsNum]; + std::thread threadFinish; + for (uint32 i = 0; i < threadsNum; ++i) { + threads[i] = std::thread(&MplScheduler::ThreadMain, this, i, EncodeThreadMainEnvironment(i)); + } + if (isSchedulerSeq) { + threadFinish = std::thread(&MplScheduler::ThreadFinish, this, EncodeThreadFinishEnvironment()); + } + for (uint32 i = 0; i < threadsNum; ++i) { + threads[i].join(); + } + if (isSchedulerSeq) { + threadFinish.join(); + } + } + return 0; +} + +int MplScheduler::FinishTask(const MplTask &task) { + TaskIdFinish(task.GetTaskId()); + return 0; +} + +void MplScheduler::Reset() { + tbTasks.clear(); + tbTaskIdsToFinish.clear(); + taskIdForAdd = 0; + taskIdToRun = 0; + taskIdExpected = 0; + numberTasks = 0; + numberTasksFinish = 0; + isSchedulerSeq = false; +} + +void MplScheduler::ThreadMain(uint32 threadID, MplSchedulerParam *env) { + MPLTimer timerTotal; + MPLTimer timerRun; + MPLTimer timerToRun; + MPLTimer timerFinish; + double timeRun = 0.0; + double timeToRun = 0.0; + double timeFinish = 0.0; + if (dumpTime) { + timerTotal.Start(); + } + DecodeThreadMainEnvironment(env); + CallbackThreadMainStart(); + if (dumpTime) { + timerToRun.Start(); + } + MplTask *task = GetTaskToRun(); + if (dumpTime) { + timerToRun.Stop(); + timeToRun += timerRun.ElapsedMicroseconds(); + } + int ret = 0; + while (task != nullptr) { + if (dumpTime) { + timerRun.Start(); + } + MplTaskParam *paramRun = CallbackGetTaskRunParam(); + task->Run(paramRun); + if (dumpTime) { + timerRun.Stop(); + timeRun += timerRun.ElapsedMicroseconds(); + timerFinish.Start(); + } + if (isSchedulerSeq) { + ret = FinishTask(*task); + CHECK_FATAL(ret == 0, "task finish failed"); + } else { + MplTaskParam *paramFinish = CallbackGetTaskFinishParam(); + ret = task->Finish(paramFinish); + CHECK_FATAL(ret == 0, "task finish failed"); + } + if (dumpTime) { + timerFinish.Stop(); + timeFinish += timerFinish.ElapsedMicroseconds(); + timerToRun.Start(); + } + task = GetTaskToRun(); + if (dumpTime) { + timerToRun.Stop(); + timeToRun += timerToRun.ElapsedMicroseconds(); + } + } + CallbackThreadMainEnd(); + if (dumpTime) { + timerTotal.Stop(); + GlobalLock(); + LogInfo::MapleLogger() << "MP TimeDump(" << schedulerName << ")::Thread" << threadID << "::ThreadMain " << + (timerTotal.ElapsedMicroseconds() / kAlternateUnits) << "ms" << std::endl; + LogInfo::MapleLogger() << "MP TimeDump(" << schedulerName << ")::Thread" << threadID << + "::ThreadMain::Task::Run " << (timeRun / kAlternateUnits) << "ms" << std::endl; + LogInfo::MapleLogger() << "MP TimeDump(" << schedulerName << ")::Thread" << threadID << + "::ThreadMain::Task::ToRun " << (timeToRun / kAlternateUnits) << "ms" << std::endl; + LogInfo::MapleLogger() << "MP TimeDump(" << schedulerName << ")::Thread" << threadID << + "::ThreadMain::Task::Finish " << (timeFinish / kAlternateUnits) << "ms" << std::endl; + GlobalUnlock(); + } +} + +void MplScheduler::ThreadFinish(MplSchedulerParam *env) { + statusFinish = kThreadRun; + DecodeThreadFinishEnvironment(env); + CallbackThreadFinishStart(); + MplTask *task = nullptr; + int ret = 0; + uint32 taskId; + while (numberTasksFinish < numberTasks) { + while (true) { + if (GetTaskIdsFinishSize() == 0) { + break; + } + task = GetTaskFinishFirst(); + CHECK_FATAL(task != nullptr, "null ptr check"); + taskId = task->GetTaskId(); + if (isSchedulerSeq) { + if (taskId != taskIdExpected) { + break; + } + } + MplTaskParam *paramFinish = CallbackGetTaskFinishParam(); + ret = task->Finish(paramFinish); + CHECK_FATAL(ret == 0, "task finish failed"); + ++numberTasksFinish; + if (isSchedulerSeq) { + ++taskIdExpected; + } + RemoveTaskFinish(task->GetTaskId()); + } + } + CallbackThreadFinishEnd(); +} +} // namespace maple \ No newline at end of file diff --git a/src/mapleall/maple_util/src/mpl_timer.cpp b/src/mapleall/maple_util/src/mpl_timer.cpp new file mode 100644 index 0000000000..f90ea63caf --- /dev/null +++ b/src/mapleall/maple_util/src/mpl_timer.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "mpl_timer.h" +#include + +namespace maple { +MPLTimer::MPLTimer() = default; + +MPLTimer::~MPLTimer() = default; + +void MPLTimer::Start() { + startTime = std::chrono::system_clock::now(); +} + +void MPLTimer::Stop() { + endTime = std::chrono::system_clock::now(); +} + +long MPLTimer::Elapsed() { + return std::chrono::duration_cast(endTime - startTime).count(); +} + +long MPLTimer::ElapsedMilliseconds() { + return std::chrono::duration_cast(endTime - startTime).count(); +} + +long MPLTimer::ElapsedMicroseconds() { + return std::chrono::duration_cast(endTime - startTime).count(); +} +} diff --git a/src/mapleall/maple_util/src/muid.cpp b/src/mapleall/maple_util/src/muid.cpp new file mode 100644 index 0000000000..93afdab671 --- /dev/null +++ b/src/mapleall/maple_util/src/muid.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/* + * We generate muid-hashcode according to the MD5 Message-Digest Algorithm here. + */ +#include "muid.h" +#include +#include "securec.h" + +/* + * Basic MUID functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~(z)))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~(z)))) + +/* + * Muid Transformation function. + */ +#define TRANS(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * Divide the whole input data into sevral groups with kGroupSizebit each and decode them. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define DECODE(n, input, output) \ + ((output)[(n)] = \ + (*reinterpret_cast(const_cast(&input[(n) * 4])))) +#else +#define DECODE(n, input, output) \ + ((output)[(n)] = \ + (unsigned int)input[(n) * 4] | \ + ((unsigned int)input[(n) * 4 + 1] << 8) | \ + ((unsigned int)input[(n) * 4 + 2] << 16) | \ + ((unsigned int)input[(n) * 4 + 3] << 24)) +#endif + +/* + * Encode function. + */ +#define ENCODE(dst, src) \ + (dst)[0] = (unsigned char)(src); \ + (dst)[1] = (unsigned char)((src) >> 8); \ + (dst)[2] = (unsigned char)((src) >> 16); \ + (dst)[3] = (unsigned char)((src) >> 24); + +/* + * Body of transformation. + */ +static const unsigned char *MuidTransform(MuidContext &status, const unsigned char &data, uint64_t count) { + unsigned int a, b, c, d; + auto *result = &data; + + while (count--) { + for (unsigned int i = 0; i < kBlockLength; i++) { + DECODE(i, result, status.block); + } + + a = status.a; + b = status.b; + c = status.c; + d = status.d; + + /* Round 1 */ + TRANS(F, a, b, c, d, status.block[0], 0xd76aa478, 7) + TRANS(F, d, a, b, c, status.block[1], 0xe8c7b756, 12) + TRANS(F, c, d, a, b, status.block[2], 0x242070db, 17) + TRANS(F, b, c, d, a, status.block[3], 0xc1bdceee, 22) + TRANS(F, a, b, c, d, status.block[4], 0xf57c0faf, 7) + TRANS(F, d, a, b, c, status.block[5], 0x4787c62a, 12) + TRANS(F, c, d, a, b, status.block[6], 0xa8304613, 17) + TRANS(F, b, c, d, a, status.block[7], 0xfd469501, 22) + TRANS(F, a, b, c, d, status.block[8], 0x698098d8, 7) + TRANS(F, d, a, b, c, status.block[9], 0x8b44f7af, 12) + TRANS(F, c, d, a, b, status.block[10], 0xffff5bb1, 17) + TRANS(F, b, c, d, a, status.block[11], 0x895cd7be, 22) + TRANS(F, a, b, c, d, status.block[12], 0x6b901122, 7) + TRANS(F, d, a, b, c, status.block[13], 0xfd987193, 12) + TRANS(F, c, d, a, b, status.block[14], 0xa679438e, 17) + TRANS(F, b, c, d, a, status.block[15], 0x49b40821, 22) + + /* Round 2 */ + TRANS(G, a, b, c, d, status.block[1], 0xf61e2562, 5) + TRANS(G, d, a, b, c, status.block[6], 0xc040b340, 9) + TRANS(G, c, d, a, b, status.block[11], 0x265e5a51, 14) + TRANS(G, b, c, d, a, status.block[0], 0xe9b6c7aa, 20) + TRANS(G, a, b, c, d, status.block[5], 0xd62f105d, 5) + TRANS(G, d, a, b, c, status.block[10], 0x02441453, 9) + TRANS(G, c, d, a, b, status.block[15], 0xd8a1e681, 14) + TRANS(G, b, c, d, a, status.block[4], 0xe7d3fbc8, 20) + TRANS(G, a, b, c, d, status.block[9], 0x21e1cde6, 5) + TRANS(G, d, a, b, c, status.block[14], 0xc33707d6, 9) + TRANS(G, c, d, a, b, status.block[3], 0xf4d50d87, 14) + TRANS(G, b, c, d, a, status.block[8], 0x455a14ed, 20) + TRANS(G, a, b, c, d, status.block[13], 0xa9e3e905, 5) + TRANS(G, d, a, b, c, status.block[2], 0xfcefa3f8, 9) + TRANS(G, c, d, a, b, status.block[7], 0x676f02d9, 14) + TRANS(G, b, c, d, a, status.block[12], 0x8d2a4c8a, 20) + + /* Round 3 */ + TRANS(H, a, b, c, d, status.block[5], 0xfffa3942, 4) + TRANS(H, d, a, b, c, status.block[8], 0x8771f681, 11) + TRANS(H, c, d, a, b, status.block[11], 0x6d9d6122, 16) + TRANS(H, b, c, d, a, status.block[14], 0xfde5380c, 23) + TRANS(H, a, b, c, d, status.block[1], 0xa4beea44, 4) + TRANS(H, d, a, b, c, status.block[4], 0x4bdecfa9, 11) + TRANS(H, c, d, a, b, status.block[7], 0xf6bb4b60, 16) + TRANS(H, b, c, d, a, status.block[10], 0xbebfbc70, 23) + TRANS(H, a, b, c, d, status.block[13], 0x289b7ec6, 4) + TRANS(H, d, a, b, c, status.block[0], 0xeaa127fa, 11) + TRANS(H, c, d, a, b, status.block[3], 0xd4ef3085, 16) + TRANS(H, b, c, d, a, status.block[6], 0x04881d05, 23) + TRANS(H, a, b, c, d, status.block[9], 0xd9d4d039, 4) + TRANS(H, d, a, b, c, status.block[12], 0xe6db99e5, 11) + TRANS(H, c, d, a, b, status.block[15], 0x1fa27cf8, 16) + TRANS(H, b, c, d, a, status.block[2], 0xc4ac5665, 23) + + /* Round 4 */ + TRANS(I, a, b, c, d, status.block[0], 0xf4292244, 6) + TRANS(I, d, a, b, c, status.block[7], 0x432aff97, 10) + TRANS(I, c, d, a, b, status.block[14], 0xab9423a7, 15) + TRANS(I, b, c, d, a, status.block[5], 0xfc93a039, 21) + TRANS(I, a, b, c, d, status.block[12], 0x655b59c3, 6) + TRANS(I, d, a, b, c, status.block[3], 0x8f0ccc92, 10) + TRANS(I, c, d, a, b, status.block[10], 0xffeff47d, 15) + TRANS(I, b, c, d, a, status.block[1], 0x85845dd1, 21) + TRANS(I, a, b, c, d, status.block[8], 0x6fa87e4f, 6) + TRANS(I, d, a, b, c, status.block[15], 0xfe2ce6e0, 10) + TRANS(I, c, d, a, b, status.block[6], 0xa3014314, 15) + TRANS(I, b, c, d, a, status.block[13], 0x4e0811a1, 21) + TRANS(I, a, b, c, d, status.block[4], 0xf7537e82, 6) + TRANS(I, d, a, b, c, status.block[11], 0xbd3af235, 10) + TRANS(I, c, d, a, b, status.block[2], 0x2ad7d2bb, 15) + TRANS(I, b, c, d, a, status.block[9], 0xeb86d391, 21) + + status.a += a; + status.b += b; + status.c += c; + status.d += d; + + result += kGroupSize; + } + + return result; +} + +/* + * Initialize constants here. + */ +void MuidInit(MuidContext &status) { + status.a = 0x67452301; + status.b = 0xefcdab89; + status.c = 0x98badcfe; + status.d = 0x10325476; + + status.count[0] = 0; + status.count[1] = 0; +} + +/* + * Decoding part(byte to unsigned int). + */ +void MuidDecode(MuidContext &status, const unsigned char &data, size_t size) { + unsigned int tmp = status.count[0]; + status.count[0] = (tmp + size) & 0x1fffffff; + if (status.count[0] < tmp) { + status.count[1]++; + } + uint32_t higherBits = static_cast(size) >> kShiftAmount; + status.count[1] += higherBits * kByteLength; + + size_t idx = tmp & kBitMask; + size_t remain = kGroupSize - idx; + auto *position = &data; + + if (idx != 0) { + if (size < remain) { + if (memcpy_s(&status.buffer[idx], kGroupSize, &data, size) != EOK) { + return; + } + return; + } + + if (memcpy_s(&status.buffer[idx], kGroupSize, &data, remain) != EOK) { + return; + } + (void)MuidTransform(status, *status.buffer, 1); + + size -= remain; + position += remain; + } + + if (size >= kGroupSize) { + position = MuidTransform(status, *position, size / kGroupSize); + size &= kBitMask; + } + + if (memcpy_s(status.buffer, kGroupSize, position, size) != EOK) { + return; + } +} + +/* + * Encoding part(unsigned int to byte). + */ +template +void FullEncode(T &result, MuidContext &status) { + size_t idx = status.count[0] & kBitMask; + status.buffer[idx++] = 0x80; + + size_t remain = kGroupSize - idx; + + if (remain < kByteLength) { + if (memset_s(&status.buffer[idx], kGroupSize, 0, remain) != EOK) { + return; + } + (void)MuidTransform(status, *status.buffer, 1); + idx = 0; + remain = kGroupSize; + } + + if (memset_s(&status.buffer[idx], kGroupSize, 0, remain - kByteLength) != EOK) { + return; + } + status.count[0] *= kByteLength; + const unsigned int indexOfLastEight = 56; + const unsigned int indexOfLastFour = 60; + ENCODE(&status.buffer[indexOfLastEight], status.count[0]) + ENCODE(&status.buffer[indexOfLastFour], status.count[1]) + + (void)MuidTransform(status, *status.buffer, 1); + ENCODE(&result[0], status.a) + ENCODE(&result[4], status.b) +} + +void MuidEncode(unsigned char (&result)[kDigestShortHashLength], MuidContext &status) { + FullEncode(result, status); + if (memset_s(&status, sizeof(status), 0, sizeof(status)) != EOK) { + return; + } +} + +void MuidEncode(unsigned char (&result)[kDigestHashLength], MuidContext &status, bool use64Bit) { + FullEncode(result, status); + if (!use64Bit) { + ENCODE(&result[8], status.c) + ENCODE(&result[12], status.d) + } + if (memset_s(&status, sizeof(status), 0, sizeof(status)) != EOK) { + return; + } +} + +/* + * The entrance functions. + */ +void GetMUIDHash(const unsigned char &data, size_t size, MUID &muid) { + MuidContext status; + MuidInit(status); + MuidDecode(status, data, size); + MuidEncode(muid.data.bytes, status); +} + +DigestHash GetDigestHash(const unsigned char &bytes, uint32_t len) { + DigestHash digestHash; + MuidContext digestContext; + + digestHash.data.first = 0; + digestHash.data.second = 0; + + MuidInit(digestContext); + MuidDecode(digestContext, bytes, len); + MuidEncode(digestHash.bytes, digestContext); + + return digestHash; +} + +MUID GetMUID(const std::string &symbolName, bool forSystem) { + MUID muid; + auto *data = reinterpret_cast(symbolName.c_str()); + GetMUIDHash(*data, symbolName.length(), muid); + if (forSystem) { + muid.SetSystemNameSpace(); + } else { + muid.SetApkNameSpace(); + } + return muid; +} \ No newline at end of file diff --git a/src/mapleall/maple_util/src/namemangler.cpp b/src/mapleall/maple_util/src/namemangler.cpp new file mode 100644 index 0000000000..425db54204 --- /dev/null +++ b/src/mapleall/maple_util/src/namemangler.cpp @@ -0,0 +1,626 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "namemangler.h" +#include +#include +#include + +namespace namemangler { +#ifdef __MRT_DEBUG +#define ASSERT(f) assert(f) +#else +#define ASSERT(f) ((void)0) +#endif + +const int kLocalCodebufSize = 1024; +const int kMaxCodecbufSize = (1 << 16); // Java spec support a max name length of 64K. + +#define GETHEXCHAR(n) static_cast((n) < 10 ? (n) + '0' : (n) - 10 + 'a') +#define GETHEXCHARU(n) static_cast((n) < 10 ? (n) + '0' : (n) - 10 + 'A') + +bool doCompression = false; + +// Store a mapping between full string and its compressed version +// More frequent and specific strings go before general ones, +// e.g. Ljava_2Flang_2FObject_3B goes before Ljava_2Flang_2F +// +using StringMap = std::map; + +const StringMap kInternalMangleTable = { + { "Ljava_2Flang_2FObject_3B", "L0_3B" }, + { "Ljava_2Flang_2FClass_3B", "L1_3B" }, + { "Ljava_2Flang_2FString_3B", "L2_3B" } +}; + +// This mapping is mainly used for compressing annotation strings +const StringMap kOriginalMangleTable = { + { "Ljava/lang/Object", "L0" }, + { "Ljava/lang/Class", "L1" }, + { "Ljava/lang/String", "L2" } +}; + +// The returned buffer needs to be explicitly freed +static inline char *AllocCodecBuf(size_t maxLen) { + if (maxLen == 0) { + return nullptr; + } + // each char may have 2 more char, so give out the max space buffer + return reinterpret_cast(malloc((maxLen <= kLocalCodebufSize) ? 3 * maxLen : 3 * kMaxCodecbufSize)); +} + +static inline void FreeCodecBuf(char *buf) { + free(buf); +} + +static std::string CompressName(std::string &name, const StringMap &mapping = kInternalMangleTable) { + for (auto &entry : mapping) { + if (name.find(entry.first) != name.npos) { + name = std::regex_replace(name, std::regex(entry.first), entry.second); + } + } + return name; +} + +static std::string DecompressName(std::string &name, const StringMap &mapping = kInternalMangleTable) { + for (auto &entry : mapping) { + if (name.find(entry.second) != name.npos) { + name = std::regex_replace(name, std::regex(entry.second), entry.first); + } + } + return name; +} + +std::string GetInternalNameLiteral(std::string name) { + return (doCompression ? CompressName(name) : name); +} + +std::string GetOriginalNameLiteral(std::string name) { + return (doCompression ? CompressName(name, kOriginalMangleTable) : name); +} + +std::string EncodeName(const std::string &name) { + // name is guaranteed to be null-terminated + size_t nameLen = name.length(); + nameLen = nameLen > kMaxCodecbufSize ? kMaxCodecbufSize : nameLen; + char *buf = AllocCodecBuf(nameLen); + if (buf == nullptr) { + return std::string(name); + } + + size_t pos = 0; + size_t i = 0; + std::string str(name); + std::u16string str16; + while (i < nameLen) { + unsigned char c = name[i]; + if (c == '_') { + buf[pos++] = '_'; + buf[pos++] = '_'; + } else if (c == '[') { + buf[pos++] = 'A'; + } else if (isalnum(c)) { + buf[pos++] = c; + } else if (c <= 0x7F) { + // _XX: '_' followed by ascii code in hex + if (c == '.') { + c = '/'; // use / in package name + } + buf[pos++] = '_'; + unsigned char n = c >> 4; // get the high 4 bit and calculate + buf[pos++] = GETHEXCHARU(n); + n = c - static_cast(n << 4); // revert + buf[pos++] = GETHEXCHARU(n); + } else { + str16.clear(); + // process one 16-bit char at a time + unsigned int n = UTF8ToUTF16(str16, str.substr(i), 1, false); + buf[pos++] = '_'; + if ((n >> 16) == 1) { + unsigned short m = str16[0]; + buf[pos++] = 'u'; + buf[pos++] = GETHEXCHAR((m & 0xF000) >> 12); + buf[pos++] = GETHEXCHAR((m & 0x0F00) >> 8); + buf[pos++] = GETHEXCHAR((m & 0x00F0) >> 4); + buf[pos++] = GETHEXCHAR(m & 0x000F); + } else { + unsigned short m = str16[0]; + buf[pos++] = 'U'; + buf[pos++] = GETHEXCHAR((m & 0xF000) >> 12); + buf[pos++] = GETHEXCHAR((m & 0x0F00) >> 8); + buf[pos++] = GETHEXCHAR((m & 0x00F0) >> 4); + buf[pos++] = GETHEXCHAR(m & 0x000F); + m = str16[1]; + buf[pos++] = GETHEXCHAR((m & 0xF000) >> 12); + buf[pos++] = GETHEXCHAR((m & 0x0F00) >> 8); + buf[pos++] = GETHEXCHAR((m & 0x00F0) >> 4); + buf[pos++] = GETHEXCHAR(m & 0x000F); + } + i += int32_t(n & 0xFFFF) - 1; + } + i++; + } + + buf[pos] = '\0'; + std::string newName = std::string(buf, pos); + FreeCodecBuf(buf); + if (doCompression) { + newName = CompressName(newName); + } + return newName; +} + +static inline bool UpdatePrimType(bool primType, int splitNo, uint32_t ch) { + if (ch == 'L') { + return false; + } + + if (((ch == ';') || (ch == '(') || (ch == ')')) && (splitNo > 1)) { + return true; + } + + return primType; +} + +const int kNumLimit = 10; +const int kCodeOffset3 = 12; +const int kCodeOffset2 = 8; +const int kCodeOffset = 4; +const int kJavaStrLength = 5; + +std::string DecodeName(const std::string &name) { + if (name.find(';') != std::string::npos) { // no need Decoding a non-encoded string + return name; + } + std::string decompressedName; + const char *namePtr = nullptr; + size_t nameLen; + + if (doCompression) { + decompressedName = name; + decompressedName = DecompressName(decompressedName); + namePtr = decompressedName.c_str(); + nameLen = decompressedName.length(); + } + else { + namePtr = name.c_str(); + nameLen = name.length(); + } + + // Demangled name is supposed to be shorter. No buffer overflow issue here. + std::string newName(nameLen, '\0'); + + bool primType = true; + int splitNo = 0; // split: class 0 | method 1 | signature 2 + size_t pos = 0; + std::string str; + std::u16string str16; + for (size_t i = 0; i < nameLen;) { + unsigned char c = namePtr[i++]; + if (c == '_') { // _XX: '_' followed by ascii code in hex + if (i >= nameLen) { + break; + } + if (namePtr[i] == '_') { + newName[pos++] = namePtr[i++]; + } else if (namePtr[i] == 'u') { + str.clear(); + str16.clear(); + i++; + c = namePtr[i++]; + uint8_t b1 = (c <= '9') ? c - '0' : c - 'a' + kNumLimit; + c = namePtr[i++]; + uint8_t b2 = (c <= '9') ? c - '0' : c - 'a' + kNumLimit; + c = namePtr[i++]; + uint8_t b3 = (c <= '9') ? c - '0' : c - 'a' + kNumLimit; + c = namePtr[i++]; + uint8_t b4 = (c <= '9') ? c - '0' : c - 'a' + kNumLimit; + uint32_t codepoint = (b1 << kCodeOffset3) | (b2 << kCodeOffset2) | (b3 << kCodeOffset) | b4; + str16 += (char16_t)codepoint; + unsigned int n = UTF16ToUTF8(str, str16, 1, false); + if ((n >> 16) == 2) { // the count of str equal 2 to 4, use array to save the utf8 results + newName[pos++] = str[0]; + newName[pos++] = str[1]; + } else if ((n >> 16) == 3) { + newName[pos++] = str[0]; + newName[pos++] = str[1]; + newName[pos++] = str[2]; + } else if ((n >> 16) == 4) { + newName[pos++] = str[0]; + newName[pos++] = str[1]; + newName[pos++] = str[2]; + newName[pos++] = str[3]; + } + } else { + c = namePtr[i++]; + unsigned int v = (c <= '9') ? c - '0' : c - 'A' + kNumLimit; + unsigned int asc = v << kCodeOffset; + if (i >= nameLen) { + break; + } + c = namePtr[i++]; + v = (c <= '9') ? c - '0' : c - 'A' + kNumLimit; + asc += v; + + newName[pos++] = static_cast(asc); + + if (asc == '|') { + splitNo++; + } + + primType = UpdatePrimType(primType, splitNo, asc); + } + } else { + if (splitNo < 2) { // split: class 0 | method 1 | signature 2 + newName[pos++] = c; + continue; + } + + primType = UpdatePrimType(primType, splitNo, c); + if (primType) { + newName[pos++] = (c == 'A') ? '[' : c; + } else { + newName[pos++] = c; + } + } + } + + newName.resize(pos); + return newName; +} + +// input: maple name +// output: Ljava/lang/Object; [Ljava/lang/Object; +void DecodeMapleNameToJavaDescriptor(const std::string &nameIn, std::string &nameOut) { + nameOut = DecodeName(nameIn); + if (nameOut[0] == 'A') { + int i = 0; + while (nameOut[i] == 'A') { + nameOut[i++] = '['; + } + } +} + +// convert maple name to java name +// http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names +std::string NativeJavaName(const std::string &name, bool overLoaded) { + // Decompress name first because the generated native function name needs + // to follow certain spec, not something maple can control. + std::string decompressedName(name); + if (doCompression) { + decompressedName = DecompressName(decompressedName); + } + + unsigned int nameLen = static_cast(decompressedName.length()) + kJavaStrLength; + std::string newName = "Java_"; + unsigned int i = 0; + + // leading A's are array + while (i < nameLen && name[i] == 'A') { + newName += "_3"; + i++; + } + + bool isProto = false; // class names in prototype have 'L' and ';' + bool isFuncname = false; + bool isTypename = false; + while (i < nameLen) { + char c = decompressedName[i]; + if (c == '_') { + i++; + // UTF16 unicode + if (decompressedName[i] == 'u') { + newName += "_0"; + i++; + } else if (decompressedName[i] == '_') { + newName += "_1"; + i++; + } else { + // _XX: '_' followed by ascii code in hex + c = decompressedName[i++]; + unsigned char v = (c <= '9') ? c - '0' : c - 'A' + kNumLimit; + unsigned char asc = v << kCodeOffset; + c = decompressedName[i++]; + v = (c <= '9') ? c - '0' : c - 'A' + kNumLimit; + asc += v; + if (asc == '/') { + newName += "_"; + } else if (asc == '|' && !isFuncname) { + newName += "_"; + isFuncname = true; + } else if (asc == '|' && isFuncname) { + if (!overLoaded) { + break; + } + newName += "_"; + isFuncname = false; + } else if (asc == '(') { + newName += "_"; + isProto = true; + } else if (asc == ')') { + break; + } else if (asc == ';' && !isFuncname) { + if (isProto) { + newName += "_2"; + } + isTypename = false; + } else if (asc == '$') { + newName += "_00024"; + } else if (asc == '-') { + newName += "_0002d"; + } else { + printf("name = %s\n", decompressedName.c_str()); + printf("c = %c\n", asc); + ASSERT(false && "more cases in NativeJavaName"); + } + } + } else { + if (c == 'L' && !isFuncname && !isTypename) { + if (isProto) { + newName += c; + } + isTypename = true; + i++; + } else if (c == 'A' && !isTypename && !isFuncname) { + while (name[i] == 'A') { + newName += "_3"; + i++; + } + } else { + newName += c; + i++; + } + } + } + return newName; +} + +static uint16_t ChangeEndian16(uint16_t u16) { + return ((u16 & 0xFF00) >> kCodeOffset2) | ((u16 & 0xFF) << kCodeOffset2); +} + +/* UTF8 + * U+0000 - U+007F 0xxxxxxx + * U+0080 - U+07FF 110xxxxx 10xxxxxx + * U+0800 - U+FFFF 1110xxxx 10xxxxxx 10xxxxxx + * U+10000- U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * UTF16 + * U+0000 - U+D7FF codePoint + * U+E000 - U+FFFF codePoint + * U+10000- U+10FFFF XXXX YYYY + * code = codePoint - 0x010000, ie, 20-bit number in the range 0x000000..0x0FFFFF + * XXXX: top 10 bits of code + 0xD800: 0xD800..0xDBFF + * YYYY: low 10 bits of code + 0xDC00: 0xDC00..0xDFFF + * + * convert upto num UTF8 elements + * return two 16-bit values: return_number_of_elements | consumed_input_number_of_elements + */ +const int kCodepointOffset1 = 6; // U+0080 - U+07FF 110xxxxx 10xxxxxx +const int kCodepointOffset2 = 12; // U+0800 - U+FFFF 1110xxxx 10xxxxxx 10xxxxxx +const int kCodepointOffset3 = 18; // U+10000- U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx +const int kCountOffset = 16; +const int kCodeAfterMinusOffset = 10; // codePoint equals itself minus 0x10000 + +unsigned UTF16ToUTF8(std::string &str, const std::u16string &str16, unsigned short num, bool isBigEndian) { + uint32_t codePoint = 0; + uint32_t i = 0; + unsigned short count = 0; + unsigned short retNum = 0; + while (i < str16.length()) { + if (isBigEndian || num == 1) { + codePoint = str16[i++]; + } else { + codePoint = ChangeEndian16(str16[i++]); + } + if (codePoint > 0xFFFF) { + codePoint &= 0x3FF; + codePoint <<= kNumLimit; + if (isBigEndian) { + codePoint += str16[i++] & 0x3FF; + } else { + codePoint += ChangeEndian16(str16[i++]) & 0x3FF; + } + } + if (codePoint <= 0x7F) { + str += static_cast(codePoint); + retNum += 1; // one UTF8 char + } else if (codePoint <= 0x7FF) { + str += static_cast(0xC0 + (codePoint >> kCodepointOffset1)); + str += static_cast(0x80 + (codePoint & 0x3F)); + retNum += 2; // two UTF8 chars + } else if (codePoint <= 0xFFFF) { + str += static_cast(0xE0 + ((codePoint >> kCodepointOffset2) & 0xF)); + str += static_cast(0x80 + ((codePoint >> kCodepointOffset1) & 0x3F)); + str += static_cast(0x80 + (codePoint & 0x3F)); + retNum += 3; // three UTF8 chars + } else { + str += static_cast(0xF0 + ((codePoint >> kCodepointOffset3) & 0x7)); + str += static_cast(0x80 + ((codePoint >> kCodepointOffset2) & 0x3F)); + str += static_cast(0x80 + ((codePoint >> kCodepointOffset1) & 0x3F)); + str += static_cast(0x80 + (codePoint & 0x3F)); + retNum += 4; // four UTF8 chars + } + count++; + if (num == count) { + return ((static_cast(retNum)) << kCountOffset) | static_cast(i); + } + } + return i; +} + +bool NeedConvertUTF16(const std::string &str8) { + uint32_t a = 0; + size_t i = 0; + size_t size = str8.length(); + while (i < size) { + a = static_cast(str8[i++]); + constexpr uint8_t maxValidAscii = 0x7F; + if (a > maxValidAscii) { + return true; + } + } + return false; +} + +uint32_t GetCodePoint(const std::string &str8, uint32_t &i) { + uint32_t b; + uint32_t c; + uint32_t d; + uint32_t codePoint = 0; + uint32_t a = static_cast(str8[i++]); + if (a <= 0x7F) { // 0... + codePoint = a; + } else if (a >= 0xF0) { // 11110... + b = str8[i++]; + c = str8[i++]; + d = str8[i++]; + codePoint = ((a & 0x7) << kCodepointOffset3) | ((b & 0x3F) << kCodepointOffset2) | + ((c & 0x3F) << kCodepointOffset1) | (d & 0x3F); + } else if (a >= 0xE0) { // 1110... + b = str8[i++]; + c = str8[i++]; + codePoint = ((a & 0xF) << kCodepointOffset2) | ((b & 0x3F) << kCodepointOffset1) | (c & 0x3F); + } else if (a >= 0xC0) { // 110... + b = str8[i++]; + codePoint = ((a & 0x1F) << kCodepointOffset1) | (b & 0x3F); + } else { + ASSERT(false && "invalid UTF-8"); + } + return codePoint; +} + +// convert upto num UTF16 elements +// two 16-bit values: return_number_of_elements | consumed_input_number_of_elements +unsigned UTF8ToUTF16(std::u16string &str16, const std::string &str8, unsigned short num, bool isBigEndian) { + uint32_t i = 0; + unsigned short count = 0; + unsigned short retNum = 0; + while (i < str8.length()) { + uint32_t codePoint = GetCodePoint(str8, i); + if (codePoint <= 0xFFFF) { + if (isBigEndian || num == 1) { + str16 += static_cast(codePoint); + } else { + str16 += static_cast(ChangeEndian16(static_cast(codePoint))); + } + retNum += 1; // one utf16 + } else { + codePoint -= 0x10000; + if (isBigEndian || num == 1) { + str16 += static_cast((codePoint >> kCodeAfterMinusOffset) | 0xD800); + str16 += static_cast((codePoint & 0x3FF) | 0xDC00); + } else { + str16 += static_cast( + ChangeEndian16(static_cast((codePoint >> kCodeAfterMinusOffset) | 0xD800))); + str16 += static_cast(ChangeEndian16((codePoint & 0x3FF) | 0xDC00)); + } + retNum += 2; // two utf16 + } + count++; + // only convert num elmements + if (num == count) { + return (static_cast(retNum) << kCountOffset) | static_cast(i); + } + } + return i; +} + +const int kGreybackOffset = 7; +void GetUnsignedLeb128Encode(std::vector &dest, uint32_t value) { + bool done = false; + do { + uint8_t byte = value & 0x7f; + value >>= kGreybackOffset; + done = (value == 0); + if (!done) { + byte |= 0x80; + } + dest.push_back(byte); + } while (!done); +} + +uint32_t GetUnsignedLeb128Decode(const uint8_t **data) { + ASSERT(data != nullptr && "data in GetUnsignedLeb128Decode() is nullptr"); + const uint8_t *ptr = *data; + uint32_t result = 0; + int shift = 0; + uint8_t byte = 0; + while (true) { + byte = *(ptr++); + result |= (byte & 0x7f) << shift; + if ((byte & 0x80) == 0) { + break; + } + shift += kGreybackOffset; + } + *data = ptr; + return result; +} + +uint64_t GetLEB128Encode(int64_t val, bool isUnsigned) { + uint64_t res = 0; + uint8_t byte = 0; + uint8_t count = 0; + bool done = false; + do { + byte = static_cast(val) & 0x7f; + val >>= kGreybackOffset; // intended signed shift: block codedex here + done = (isUnsigned ? val == 0 : (val == 0 || val == -1)); + if (!done) { + byte |= 0x80; + } + res |= (static_cast(byte) << (count++ << 3)); // each byte need 8 bit + } while (!done); + return res; +} + +uint64_t GetUleb128Encode(uint64_t val) { + return GetLEB128Encode(int64_t(val), true); +} + +uint64_t GetSleb128Encode(int64_t val) { + return GetLEB128Encode(val, false); +} + +uint64_t GetUleb128Decode(uint64_t val) { + return val; +} + +int64_t GetSleb128Decode(uint64_t val) { + return val; +} + +size_t GetUleb128Size(uint64_t v) { + ASSERT(v && "if v == 0, __builtin_clzll(v) is not defined"); + size_t clz = static_cast(__builtin_clzll(v)); + // num of 7-bit groups + return size_t((64 - clz + 6) / 7); +} + +size_t GetSleb128Size(int32_t v) { + size_t size = 0; + int rem = v >> kGreybackOffset; + bool hasMore = true; + int end = ((v >= 0) ? 0 : -1); + + while (hasMore) { + hasMore = (rem != end) || ((rem & 1) != ((v >> 6) & 1)); // judege whether has More valid rem + size++; + v = rem; + rem >>= kGreybackOffset; // intended signed shift: block codedex here + } + return size; +} +} // namespace namemangler diff --git a/src/mapleall/maple_util/src/string_utils.cpp b/src/mapleall/maple_util/src/string_utils.cpp new file mode 100644 index 0000000000..2a9f25fb55 --- /dev/null +++ b/src/mapleall/maple_util/src/string_utils.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) [2019] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "string_utils.h" +#include +#include + +namespace maple { +std::string StringUtils::Trim(const std::string &src) { + // remove space + return std::regex_replace(src, std::regex("\\s+"), ""); +} + +std::string StringUtils::Replace(const std::string &src, const std::string &target, + const std::string &replacement) { + std::string::size_type replaceLen = replacement.size(); + std::string::size_type targetLen = target.size(); + std::string temp = src; + std::string::size_type index = 0; + index = temp.find(target, index); + while (index != std::string::npos) { + temp.replace(index, targetLen, replacement); + index += replaceLen; + index = temp.find(target, index); + } + return temp; +} + +std::string StringUtils::Append(const std::string &src, const std::string &target, const std::string &spliter) { + return src + spliter + target; +} + +std::string StringUtils::GetStrAfterLast(const std::string &src, const std::string &target, + bool isReturnEmpty) { + size_t pos = src.find_last_of(target); + if (pos == std::string::npos) { + return isReturnEmpty ? "" : src; + } + return src.substr(pos + 1); +} + +std::string StringUtils::GetStrBeforeLast(const std::string &src, const std::string &target, bool isReturnEmpty) { + size_t pos = src.find_last_of(target); + if (pos == std::string::npos) { + return isReturnEmpty ? "" : src; + } + return src.substr(0, pos); +} + +void StringUtils::Split(const std::string &src, std::unordered_set &container, char delim) { + if (Trim(src).empty()) { + return; + } + std::stringstream strStream(src + delim); + std::string item; + while (std::getline(strStream, item, delim)) { + container.insert(item); + } +} + +std::regex StringUtils::kCommandInjectionRegex("[;\\|\\&\\$\\>\\<`]"); +} // namespace maple diff --git a/src/mapleall/maple_util/src/thread_env.cpp b/src/mapleall/maple_util/src/thread_env.cpp new file mode 100644 index 0000000000..5dcae88fbc --- /dev/null +++ b/src/mapleall/maple_util/src/thread_env.cpp @@ -0,0 +1,19 @@ +/* + * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "thread_env.h" + +namespace maple { +ThreadEnv ThreadEnv::threadEnv; +} // namespace maple -- Gitee