Execute TranslateClasses in other thread

Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IA7GHA?from=project-issue
Test: Build & Boot devices

Signed-off-by: wupengyong <wupengyong@huawei.com>
Change-Id: I463165678ac1b3079e7e22fc19088deae70563a6
This commit is contained in:
wupengyong 2024-07-02 15:38:59 +08:00
parent 5237fdd0f4
commit f032571cb7
9 changed files with 225 additions and 2 deletions

View File

@ -198,6 +198,7 @@ void EcmaVM::PreFork()
heap_->AdjustSpaceSizeForAppSpawn();
heap_->GetReadOnlySpace()->SetReadOnly();
heap_->DisableParallelGC();
SetPostForked(false);
SharedHeap::GetInstance()->DisableParallelGC(thread_);
}
@ -207,6 +208,7 @@ void EcmaVM::PostFork()
heap_->SetHeapMode(HeapMode::SHARE);
GetAssociatedJSThread()->PostFork();
Taskpool::GetCurrentTaskpool()->Initialize();
SetPostForked(true);
LOG_ECMA(INFO) << "multi-thread check enabled: " << options_.EnableThreadCheck();
#if defined(JIT_ESCAPE_ENABLE) || defined(AOT_ESCAPE_ENABLE)
SignalAllReg();

View File

@ -131,6 +131,21 @@ public:
return initialized_;
}
void SetPostForked(bool isPostForked)
{
isPostForked_ = isPostForked;
}
bool IsPostForked() const
{
return isPostForked_;
}
bool IsAsynTranslateClasses()
{
return IsPostForked() && GetJSOptions().IsAsyncLoadAbc();
}
ObjectFactory *GetFactory() const
{
return factory_;
@ -838,6 +853,7 @@ private:
JSRuntimeOptions options_;
bool icEnabled_ {true};
bool initialized_ {false};
bool isPostForked_ {false};
GCStats *gcStats_ {nullptr};
GCKeyStats *gcKeyStats_ {nullptr};
EcmaStringTable *stringTable_ {nullptr};

View File

@ -185,7 +185,8 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
"--compiler-opt-induction-variable: Enable induciton variable analysis for aot compiler. Default: 'false'\n"
"--compiler-trace-induction-variable: Enable tracing induction variable for aot compiler. Default: 'false'\n"
"--compiler-memory-analysis: Enable memory analysis for aot compiler. Default: 'true'\n"
"--compiler-enable-jit-fast-compile: Enable jit fast compile. Default: 'false'\n\n";
"--compiler-enable-jit-fast-compile: Enable jit fast compile. Default: 'false'\n"
"--async-load-abc: Enable asynchronous load abc. Default: 'true'\n\n";
bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
{
@ -312,6 +313,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
{"compiler-baselinejit-hotness-threshold", required_argument, nullptr, OPTION_COMPILER_BASELINEJIT_HOTNESS_THRESHOLD},
{"compiler-force-baselinejit-compile-main", required_argument, nullptr, OPTION_COMPILER_FORCE_BASELINEJIT_COMPILE_MAIN},
{"compiler-enable-jit-fast-compile", required_argument, nullptr, OPTION_COMPILER_ENABLE_JIT_FAST_COMPILE},
{"async-load-abc", required_argument, nullptr, OPTION_ASYNC_LOAD_ABC},
{nullptr, 0, nullptr, 0},
};
@ -1188,6 +1190,14 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
return false;
}
break;
case OPTION_ASYNC_LOAD_ABC:
ret = ParseBoolParam(&argBool);
if (ret) {
SetAsyncLoadAbc(argBool);
} else {
return false;
}
break;
default:
LOG_ECMA(ERROR) << "Invalid option\n";
return false;

View File

@ -196,6 +196,7 @@ enum CommandValues {
OPTION_ENABLE_AOT_CRASH_ESCAPE,
OPTION_COMPILER_ENABLE_JIT_FAST_COMPILE,
OPTION_COMPILER_BASELINE_PGO,
OPTION_ASYNC_LOAD_ABC,
};
static_assert(OPTION_SPLIT_ONE == 64);
@ -1808,6 +1809,16 @@ public:
return enableFrameworkAOT_;
}
void SetAsyncLoadAbc(bool value)
{
asyncLoadAbc_ = value;
}
bool IsAsyncLoadAbc() const
{
return asyncLoadAbc_;
}
public:
static constexpr int32_t MAX_APP_COMPILE_METHOD_SIZE = 1_KB;
@ -1974,6 +1985,7 @@ private:
bool enableJitFrame_{false};
bool disableCodeSign_{false};
bool enableBaselinePgo_{false};
bool asyncLoadAbc_ {true};
};
} // namespace panda::ecmascript

View File

@ -131,6 +131,7 @@ uint32_t JSPandaFile::GetOrInsertConstantPool(ConstPoolType type, uint32_t offse
void JSPandaFile::InitializeUnMergedPF()
{
Span<const uint32_t> classIndexes = pf_->GetClasses();
numClasses_ = classIndexes.size();
JSRecordInfo info;
for (const uint32_t index : classIndexes) {
panda_file::File::EntityId classId(index);
@ -172,6 +173,7 @@ void JSPandaFile::InitializeUnMergedPF()
void JSPandaFile::InitializeMergedPF()
{
Span<const uint32_t> classIndexes = pf_->GetClasses();
numClasses_ = classIndexes.size();
for (const uint32_t index : classIndexes) {
panda_file::File::EntityId classId(index);
if (pf_->IsExternal(classId)) {
@ -449,4 +451,94 @@ void JSPandaFile::ClearNameMap()
recordNameMap_.clear();
}
}
size_t JSPandaFile::GetClassAndMethodIndex(size_t *methodIdx)
{
LockHolder lock(classIndexMutex_);
size_t result = 0;
Span<const uint32_t> classIndexes = GetClasses();
uint32_t index = 0;
do {
result = classIndex_++;
if (result >= numClasses_) {
return result;
}
index = classIndexes[result];
} while (IsExternal(panda_file::File::EntityId(index)));
*methodIdx = methodIndex_;
panda_file::File::EntityId classId(classIndexes[result]);
panda_file::ClassDataAccessor cda(*pf_, classId);
methodIndex_ += cda.GetMethodsNumber();
return result;
}
bool JSPandaFile::TranslateClassesTask::Run([[maybe_unused]] uint32_t threadIndex)
{
jsPandaFile_->TranslateClass(thread_, *methodNamePtr_);
jsPandaFile_->ReduceTaskCount();
return true;
}
void JSPandaFile::TranslateClass(JSThread *thread, const CString &methodName)
{
size_t methodIdx = 0;
size_t classIdx = GetClassAndMethodIndex(&methodIdx);
while (classIdx < numClasses_) {
PandaFileTranslator::TranslateClass(thread, this, methodName, methodIdx, classIdx);
classIdx = GetClassAndMethodIndex(&methodIdx);
}
}
void JSPandaFile::PostInitializeMethodTask(JSThread *thread, const std::shared_ptr<CString> &methodNamePtr)
{
IncreaseTaskCount();
Taskpool::GetCurrentTaskpool()->PostTask(
std::make_unique<TranslateClassesTask>(thread->GetThreadId(), thread, this, methodNamePtr));
}
void JSPandaFile::IncreaseTaskCount()
{
LockHolder holder(waitTranslateClassFinishedMutex_);
runningTaskCount_++;
}
void JSPandaFile::WaitTranslateClassTaskFinished()
{
LockHolder holder(waitTranslateClassFinishedMutex_);
while (runningTaskCount_ > 0) {
waitTranslateClassFinishedCV_.Wait(&waitTranslateClassFinishedMutex_);
}
}
void JSPandaFile::ReduceTaskCount()
{
LockHolder holder(waitTranslateClassFinishedMutex_);
runningTaskCount_--;
if (runningTaskCount_ == 0) {
waitTranslateClassFinishedCV_.SignalAll();
}
}
void JSPandaFile::SetAllMethodLiteralToMap()
{
// async to optimize SetAllMethodLiteralToMap later
MethodLiteral *methodLiterals = GetMethodLiterals();
size_t methodIdx = 0;
while (methodIdx < numMethods_) {
MethodLiteral *methodLiteral = methodLiterals + (methodIdx++);
SetMethodLiteralToMap(methodLiteral);
}
}
void JSPandaFile::TranslateClasses(JSThread *thread, const CString &methodName)
{
const std::shared_ptr<CString> methodNamePtr = std::make_shared<CString>(methodName);
for (int i = 0; i < Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); i++) {
PostInitializeMethodTask(thread, methodNamePtr);
}
TranslateClass(thread, methodName);
WaitTranslateClassTaskFinished();
SetAllMethodLiteralToMap();
}
} // namespace panda::ecmascript

View File

@ -21,6 +21,7 @@
#include "ecmascript/jspandafile/method_literal.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/taskpool/task.h"
#include "libpandafile/file-inl.h"
#include "libpandafile/file_items.h"
@ -89,6 +90,23 @@ public:
JSPandaFile(const panda_file::File *pf, const CString &descriptor);
~JSPandaFile();
class TranslateClassesTask : public Task {
public:
TranslateClassesTask(int32_t id, JSThread *thread, JSPandaFile *jsPandaFile,
const std::shared_ptr<CString> &methodNamePtr)
: Task(id), thread_(thread), jsPandaFile_(jsPandaFile), methodNamePtr_(methodNamePtr) {};
~TranslateClassesTask() override = default;
bool Run(uint32_t threadIndex) override;
NO_COPY_SEMANTIC(TranslateClassesTask);
NO_MOVE_SEMANTIC(TranslateClassesTask);
private:
JSThread *thread_ {nullptr};
JSPandaFile *jsPandaFile_ {nullptr};
std::shared_ptr<CString> methodNamePtr_;
};
const CString &GetJSPandaFileDesc() const
{
return desc_;
@ -440,10 +458,29 @@ public:
}
void ClearNameMap();
void TranslateClasses(JSThread *thread, const CString &methodName);
private:
void InitializeUnMergedPF();
void InitializeMergedPF();
void WaitTranslateClassTaskFinished();
void NotifyTranslateClassTaskCompleted();
void IncreaseTaskCount();
void TranslateClass(JSThread *thread, const CString &methodName);
void PostInitializeMethodTask(JSThread *thread, const std::shared_ptr<CString> &methodNamePtr);
void ReduceTaskCount();
void SetAllMethodLiteralToMap();
size_t GetClassAndMethodIndex(size_t *methodIdx);
static constexpr size_t VERSION_SIZE = 4;
static constexpr std::array<uint8_t, VERSION_SIZE> OLD_VERSION {0, 0, 0, 2};
@ -457,9 +494,16 @@ private:
CUnorderedMap<uint32_t, CString> recordNameMap_;
Mutex methodNameMapMutex_;
Mutex recordNameMapMutex_;
Mutex waitTranslateClassFinishedMutex_;
Mutex classIndexMutex_;
ConditionVariable waitTranslateClassFinishedCV_;
uint32_t runningTaskCount_ {0};
size_t classIndex_ {0};
size_t methodIndex_ {0};
CUnorderedMap<uint32_t, uint64_t> constpoolMap_;
uint32_t numMethods_ {0};
uint32_t numClasses_ {0};
MethodLiteral *methodLiterals_ {nullptr};
CString desc_;
uint32_t anFileInfoIndex_ {INVALID_INDEX};

View File

@ -544,7 +544,11 @@ std::shared_ptr<JSPandaFile> JSPandaFileManager::GenerateJSPandaFile(JSThread *t
methodName = JSPandaFile::ENTRY_FUNCTION_NAME;
}
}
PandaFileTranslator::TranslateClasses(thread, newJsPandaFile.get(), methodName);
if (newJsPandaFile->IsNewVersion() && vm->IsAsynTranslateClasses()) {
newJsPandaFile->TranslateClasses(thread, methodName);
} else {
PandaFileTranslator::TranslateClasses(thread, newJsPandaFile.get(), methodName);
}
{
LockHolder lock(jsPandaFileLock_);

View File

@ -102,6 +102,47 @@ void PandaFileTranslator::TranslateClasses(const JSThread *thread, JSPandaFile *
}
}
void PandaFileTranslator::TranslateClass(const JSThread *thread, JSPandaFile *jsPandaFile,
const CString &methodName, size_t methodIdx, size_t classIdx)
{
ASSERT(jsPandaFile != nullptr && jsPandaFile->GetMethodLiterals() != nullptr);
MethodLiteral *methodLiterals = jsPandaFile->GetMethodLiterals();
const panda_file::File *pf = jsPandaFile->GetPandaFile();
Span<const uint32_t> classIndexes = jsPandaFile->GetClasses();
const uint32_t index = classIndexes[classIdx];
panda_file::File::EntityId classId(index);
panda_file::ClassDataAccessor cda(*pf, classId);
CString recordName = JSPandaFile::ParseEntryPoint(utf::Mutf8AsCString(cda.GetDescriptor()));
bool isUpdateMainMethodIndex = false;
cda.EnumerateMethods([thread, jsPandaFile, methodLiterals, &methodIdx, pf, &methodName,
&recordName, &isUpdateMainMethodIndex]
(panda_file::MethodDataAccessor &mda) {
auto methodId = mda.GetMethodId();
CString name = reinterpret_cast<const char *>(jsPandaFile->GetStringData(mda.GetNameId()).data);
auto methodOffset = methodId.GetOffset();
if (jsPandaFile->IsBundlePack()) {
if (!isUpdateMainMethodIndex && name == methodName) {
jsPandaFile->UpdateMainMethodIndex(methodOffset);
isUpdateMainMethodIndex = true;
}
} else {
if (!isUpdateMainMethodIndex && JSPandaFile::IsEntryOrPatch(name)) {
jsPandaFile->UpdateMainMethodIndex(methodOffset, recordName);
isUpdateMainMethodIndex = true;
}
}
MethodLiteral *methodLiteral = methodLiterals + (methodIdx++);
InitializeMemory(methodLiteral, methodId);
methodLiteral->Initialize(jsPandaFile, thread);
// IsNewVersion
panda_file::IndexAccessor indexAccessor(*pf, methodId);
panda_file::FunctionKind funcKind = indexAccessor.GetFunctionKind();
FunctionKind kind = JSPandaFile::GetFunctionKind(funcKind);
methodLiteral->SetFunctionKind(kind);
});
}
JSHandle<Program> PandaFileTranslator::GenerateProgram(EcmaVM *vm, const JSPandaFile *jsPandaFile,
std::string_view entryPoint)
{

View File

@ -38,6 +38,8 @@ public:
static JSHandle<Program> GenerateProgram(EcmaVM *vm, const JSPandaFile *jsPandaFile,
std::string_view entryPoint);
static void TranslateClasses(const JSThread *thread, JSPandaFile *jsPandaFile, const CString &methodName);
static void TranslateClass(const JSThread *thread, JSPandaFile *jsPandaFile, const CString &methodName,
size_t methodIdx, size_t classIdx);
private:
static JSHandle<Program> GenerateProgramInternal(EcmaVM *vm, MethodLiteral *mainMethodLiteral,