From c33972410f10cc740ef36912f7e65c4d0ebf8966 Mon Sep 17 00:00:00 2001 From: Onlynagesha Date: Tue, 9 Sep 2025 19:30:24 +0800 Subject: [PATCH] PAOC AOT parallel compilation (Experimental) Issue: (todo) Signed-off-by: Onlynagesha Change-Id: I88dda208f94983a82b6606d914569a2790561c15 --- .../optimizer/code_generator/codegen.cpp | 4 +- static_core/compiler/optimizer/ir/aot_data.h | 4 + static_core/compiler/optimizer/pipeline.cpp | 38 +- static_core/compiler/optimizer/pipeline.h | 5 +- static_core/compiler/optimizer_run.h | 4 +- static_core/compiler/tests/aot_test.cpp | 138 ------ static_core/compiler/tools/paoc/paoc.cpp | 460 +++++++++++++----- static_core/compiler/tools/paoc/paoc.h | 75 ++- static_core/compiler/tools/paoc/paoc_llvm.cpp | 2 +- static_core/docs/task_manager.md | 8 +- .../tests/taskmanager/task_scheduler_test.cpp | 5 + static_core/runtime/class_linker.cpp | 4 - static_core/runtime/locks.cpp | 9 - static_core/runtime/mem/heap_manager.cpp | 6 - static_core/tests/checked/CMakeLists.txt | 1 - 15 files changed, 435 insertions(+), 328 deletions(-) diff --git a/static_core/compiler/optimizer/code_generator/codegen.cpp b/static_core/compiler/optimizer/code_generator/codegen.cpp index d8a8a9b99b..07974779d2 100644 --- a/static_core/compiler/optimizer/code_generator/codegen.cpp +++ b/static_core/compiler/optimizer/code_generator/codegen.cpp @@ -379,7 +379,9 @@ bool Codegen::BeginMethod() } if (GetGraph()->IsAotMode()) { - GetEncoder()->SetCodeOffset(GetGraph()->GetAotData()->GetCodeOffset() + CodeInfo::GetCodeOffset(GetArch())); + auto offset = GetGraph()->GetAotData()->GetCodeOffset() + CodeInfo::GetCodeOffset(GetArch()); + LOG(DEBUG, COMPILER) << "GetEncoder()->SetCodeOffset(offset=" << offset << ")"; + GetEncoder()->SetCodeOffset(offset); } else { GetEncoder()->SetCodeOffset(0); } diff --git a/static_core/compiler/optimizer/ir/aot_data.h b/static_core/compiler/optimizer/ir/aot_data.h index daf17d356e..a476729791 100644 --- a/static_core/compiler/optimizer/ir/aot_data.h +++ b/static_core/compiler/optimizer/ir/aot_data.h @@ -95,6 +95,10 @@ public: int32_t GetPltSlotId(uint32_t methodId, uint32_t fileIndex); int32_t GetIntfInlineCacheSlotId(uint64_t cacheIdx); + void SetCodeOffset(AddressType codeAddr) + { + codeAddress_ = codeAddr; + } AddressType GetCodeOffset() const { return codeAddress_; diff --git a/static_core/compiler/optimizer/pipeline.cpp b/static_core/compiler/optimizer/pipeline.cpp index 8edff74bf2..65ca294842 100644 --- a/static_core/compiler/optimizer/pipeline.cpp +++ b/static_core/compiler/optimizer/pipeline.cpp @@ -80,7 +80,7 @@ std::unique_ptr Pipeline::Create(Graph *graph) } } -static inline bool RunCodegenPass(Graph *graph) +bool Pipeline::RunCodegenPass(Graph *graph) { if (graph->GetMethodProperties().GetRequireFrameSetup()) { return graph->RunPass(); @@ -90,7 +90,7 @@ static inline bool RunCodegenPass(Graph *graph) /* static */ template -void Pipeline::Run(CompilerTaskRunner taskRunner) +void Pipeline::Run(CompilerTaskRunner taskRunner, bool skipsCodegen) { auto pipeline = taskRunner.GetContext().GetPipeline(); auto *graph = pipeline->GetGraph(); @@ -110,8 +110,8 @@ void Pipeline::Run(CompilerTaskRunner taskRunner) } if (!g_options.IsCompilerNonOptimizing()) { - taskRunner.SetTaskOnSuccess([](CompilerTaskRunner nextRunner) { - Pipeline::RunRegAllocAndCodeGenPass(std::move(nextRunner)); + taskRunner.SetTaskOnSuccess([skipsCodegen](CompilerTaskRunner nextRunner) { + Pipeline::RunRegAllocAndCodeGenPass(std::move(nextRunner), skipsCodegen); }); bool success = pipeline->RunOptimizations(); CompilerTaskRunner::EndTask(std::move(taskRunner), success); @@ -126,12 +126,12 @@ void Pipeline::Run(CompilerTaskRunner taskRunner) CompilerTaskRunner::EndTask(std::move(taskRunner), false); return; } - Pipeline::RunRegAllocAndCodeGenPass(std::move(taskRunner)); + Pipeline::RunRegAllocAndCodeGenPass(std::move(taskRunner), skipsCodegen); } /* static */ template -void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner taskRunner) +void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner taskRunner, bool regAllocOnly) { auto *graph = taskRunner.GetContext().GetPipeline()->GetGraph(); bool fatalOnErr = !g_options.IsCompilerAllowBackendFailures(); @@ -147,15 +147,17 @@ void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner taskRun } graph->template RunPass(); - taskRunner.SetTaskOnSuccess([fatalOnErr](CompilerTaskRunner nextRunner) { - nextRunner.AddCallbackOnFail([fatalOnErr]([[maybe_unused]] CompilerContext &compilerCtx) { - if (fatalOnErr) { - LOG(FATAL, COMPILER) << "RunOptimizations failed: code generation error"; - } + if (!regAllocOnly) { + taskRunner.SetTaskOnSuccess([fatalOnErr](CompilerTaskRunner nextRunner) { + nextRunner.AddCallbackOnFail([fatalOnErr]([[maybe_unused]] CompilerContext &compilerCtx) { + if (fatalOnErr) { + LOG(FATAL, COMPILER) << "RunOptimizations failed: code generation error"; + } + }); + bool success = RunCodegenPass(nextRunner.GetContext().GetPipeline()->GetGraph()); + CompilerTaskRunner::EndTask(std::move(nextRunner), success); }); - bool success = RunCodegenPass(nextRunner.GetContext().GetPipeline()->GetGraph()); - CompilerTaskRunner::EndTask(std::move(nextRunner), success); - }); + } bool success = RegAlloc(graph); if (!success && fatalOnErr) { LOG(FATAL, COMPILER) << "RunOptimizations failed: register allocation error"; @@ -277,9 +279,9 @@ bool Pipeline::RunOptimizations() return true; } -template void Pipeline::Run(CompilerTaskRunner); -template void Pipeline::Run(CompilerTaskRunner); -template void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner); -template void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner); +template void Pipeline::Run(CompilerTaskRunner, bool); +template void Pipeline::Run(CompilerTaskRunner, bool); +template void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner, bool); +template void Pipeline::RunRegAllocAndCodeGenPass(CompilerTaskRunner, bool); } // namespace ark::compiler diff --git a/static_core/compiler/optimizer/pipeline.h b/static_core/compiler/optimizer/pipeline.h index 43a3bccb61..a130b20848 100644 --- a/static_core/compiler/optimizer/pipeline.h +++ b/static_core/compiler/optimizer/pipeline.h @@ -44,13 +44,14 @@ public: } template - static void Run(CompilerTaskRunner taskRunner); + static void Run(CompilerTaskRunner taskRunner, bool skipsCodegen = false); + static bool RunCodegenPass(Graph *graph); static std::unique_ptr Create(Graph *graph); private: template - static void RunRegAllocAndCodeGenPass(CompilerTaskRunner taskRunner); + static void RunRegAllocAndCodeGenPass(CompilerTaskRunner taskRunner, bool regAllocOnly = false); Graph *graph_ {nullptr}; }; diff --git a/static_core/compiler/optimizer_run.h b/static_core/compiler/optimizer_run.h index a11fff394e..8f8ed541b8 100644 --- a/static_core/compiler/optimizer_run.h +++ b/static_core/compiler/optimizer_run.h @@ -25,7 +25,7 @@ namespace ark::compiler { class Graph; template -inline void RunOptimizations(CompilerTaskRunner taskRunner) +inline void RunOptimizations(CompilerTaskRunner taskRunner, bool skipsCodegen = false) { auto &taskCtx = taskRunner.GetContext(); auto pipeline = Pipeline::Create(taskCtx.GetGraph()); @@ -34,7 +34,7 @@ inline void RunOptimizations(CompilerTaskRunner taskRunner) } else { taskCtx.SetPipeline(pipeline.get()); } - Pipeline::Run(std::move(taskRunner)); + Pipeline::Run(std::move(taskRunner), skipsCodegen); } } // namespace ark::compiler diff --git a/static_core/compiler/tests/aot_test.cpp b/static_core/compiler/tests/aot_test.cpp index 698e8bae56..c33920ee19 100644 --- a/static_core/compiler/tests/aot_test.cpp +++ b/static_core/compiler/tests/aot_test.cpp @@ -729,144 +729,6 @@ TEST_F(AotTest, FileManagerLoadAbc) RunAotdump(aotFname.GetFileName()); } -static void PaocClustersWriteJson(const TmpFile &paocClusters) -{ - std::ofstream(paocClusters.GetFileName()) << - R"( - { - "clusters_map" : - { - "A::count" : ["unroll_enable"], - "B::count2" : ["unroll_disable"], - "_GLOBAL::main" : ["inline_disable", 1] - }, - - "compiler_options" : - { - "unroll_disable" : - { - "compiler-loop-unroll" : "false" - }, - - "unroll_enable" : - { - "compiler-loop-unroll" : "true", - "compiler-loop-unroll-factor" : 42, - "compiler-loop-unroll-inst-limit" : 850 - }, - - "inline_disable" : - { - "compiler-inlining" : "false" - } - } - } - )"; -} - -static void PaocClustersEmit(const TmpFile &pandaFname) -{ - auto source = R"( - .record A {} - .record B {} - - .function i32 A.count() { - movi v1, 5 - ldai 0 - main_loop: - jeq v1, main_ret - addi 1 - jmp main_loop - main_ret: - return - } - - .function i32 B.count() { - movi v1, 5 - ldai 0 - main_loop: - jeq v1, main_ret - addi 1 - jmp main_loop - main_ret: - return - } - - .function i32 B.count2() { - movi v1, 5 - ldai 0 - main_loop: - jeq v1, main_ret - addi 1 - jmp main_loop - main_ret: - return - } - - .function i32 main() { - call.short A.count - sta v0 - call.short B.count - add2 v0 - call.short B.count2 - add2 v0 - return - } - )"; - - pandasm::Parser parser; - auto res = parser.Parse(source); - ASSERT_TRUE(res); - ASSERT_TRUE(pandasm::AsmEmitter::Emit(pandaFname.GetFileName(), res.Value())); -} - -TEST_F(AotTest, PaocClusters) -{ - // Test basic functionality only in host mode. - if (RUNTIME_ARCH != Arch::X86_64) { - return; - } - - TmpFile paocClusters("clusters.json"); - PaocClustersWriteJson(paocClusters); - - TmpFile pandaFname("test.pf"); - PaocClustersEmit(pandaFname); - - { - TmpFile compilerEvents("events.csv"); - auto res = - os::exec::Exec(GetPaocFile(), "--paoc-panda-files", pandaFname.GetFileName(), "--paoc-clusters", - paocClusters.GetFileName(), "--compiler-loop-unroll-factor=7", - "--compiler-enable-events=true", "--compiler-events-path", compilerEvents.GetFileName()); - ASSERT_TRUE(res) << "paoc failed with error: " << res.Error().ToString(); - ASSERT_EQ(res.Value(), 0U); - - bool firstFound = false; - bool secondFound = false; - std::ifstream eventsFile(compilerEvents.GetFileName()); - - std::regex rgxUnrollAppliedCluster("A::count,loop-unroll,.*,unroll_factor:42,.*"); - std::regex rgxUnrollRestoredDefault("B::count,loop-unroll,.*,unroll_factor:7,.*"); - - for (std::string line; std::getline(eventsFile, line);) { - if (line.rfind("loop-unroll") != std::string::npos) { - if (!firstFound) { - // Check that the cluster is applied: - ASSERT_TRUE(std::regex_match(line, rgxUnrollAppliedCluster)); - firstFound = true; - continue; - } - ASSERT_FALSE(secondFound); - // Check that the option is restored: - ASSERT_TRUE(std::regex_match(line, rgxUnrollRestoredDefault)); - secondFound = true; - } - } - ASSERT_TRUE(firstFound && secondFound); - } -} - static void PandaFilesEmitFirst(const TmpFile &pandaFname) { auto source = R"( diff --git a/static_core/compiler/tools/paoc/paoc.cpp b/static_core/compiler/tools/paoc/paoc.cpp index 71df4e7289..e0368c574c 100644 --- a/static_core/compiler/tools/paoc/paoc.cpp +++ b/static_core/compiler/tools/paoc/paoc.cpp @@ -14,6 +14,7 @@ */ #include "libarkfile/class_data_accessor.h" +#include "libpandabase/taskmanager/task_manager.h" #include "paoc_options.h" #include "aot/compiled_method.h" #include "paoc_clusters.h" @@ -40,12 +41,23 @@ namespace ark::paoc { // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define LOG_PAOC(level) LOG(level, COMPILER) << "PAOC: " +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define LOG_PAOC_VERBOSE \ + if (paocOptions_->IsPaocVerbose()) \ + LOG_PAOC(DEBUG) Paoc::CompilingContext::CompilingContext(Method *methodPtr, size_t methodIndex, std::ofstream *statisticsDump) + : CompilingContext(methodPtr, methodIndex, -1U, statisticsDump) +{ +} + +Paoc::CompilingContext::CompilingContext(Method *methodPtr, size_t methodIndex, size_t taskIndex, + std::ofstream *statisticsDump) : method(methodPtr), allocator(ark::SpaceType::SPACE_TYPE_COMPILER, PandaVM::GetCurrent()->GetMemStats(), true), graphLocalAllocator(ark::SpaceType::SPACE_TYPE_COMPILER, PandaVM::GetCurrent()->GetMemStats(), true), - index(methodIndex), + methodIndex(methodIndex), + taskIndex(taskIndex), stats(statisticsDump) { } @@ -60,6 +72,7 @@ Paoc::CompilingContext::~CompilingContext() DumpStatistics(); } } + void Paoc::CompilingContext::DumpStatistics() const { ASSERT(stats); @@ -70,6 +83,66 @@ void Paoc::CompilingContext::DumpStatistics() const *stats << graphLocalAllocator.GetAllocatedSize() << '\n'; } +void Paoc::ParallelCompilingContext::SubmitCompiledTask(TaskContextHandle &&task) +{ + auto lh = os::memory::LockHolder {submissionMutex_}; + submittedTasks_.emplace(std::move(task)); + aotBuilderCv_.SignalAll(); +} + +Paoc::ParallelCompilingContext::TaskContextHandle Paoc::ParallelCompilingContext::PopCompiledTask(size_t index) +{ + { + auto lh = os::memory::LockHolder {submissionMutex_}; + while (submittedTasks_.empty() || (*submittedTasks_.begin())->taskIndex != index) { + aotBuilderCv_.Wait(&submissionMutex_); + } + } + auto lh = os::memory::LockHolder {submissionMutex_}; + auto node = submittedTasks_.extract(submittedTasks_.begin()); + return std::move(node.value()); +} + +Paoc::AotBuilderContext::~AotBuilderContext() +{ + EndCurrentClass(); + EndCurrentFile(); +} + +void Paoc::AotBuilderContext::EndCurrentClass() +{ + if (curClass_ == nullptr) { + return; + } + self_->aotBuilder_->EndClass(); +} + +void Paoc::AotBuilderContext::EndCurrentFile() +{ + if (curFile_ == nullptr) { + return; + } + self_->BuildClassHashTable(*curFile_); + self_->aotBuilder_->EndFile(); +} + +void Paoc::AotBuilderContext::Proceed(const panda_file::File *pfile, Class *klass) +{ + if (klass == curClass_) { + return; + } + EndCurrentClass(); + // Note: pfile->GetFilename() and klass->GetPandaFile()->GetFilename() may be different strings + // (one is absolute path and the other is relative). + if (pfile != curFile_) { + EndCurrentFile(); + curFile_ = pfile; + self_->StartAotFile(*curFile_); + } + curClass_ = klass; + self_->aotBuilder_->StartClass(*curClass_); +} + /// A class that encloses paoc's initialization: class Paoc::PaocInitializer { public: @@ -448,6 +521,7 @@ void Paoc::StartAotFile(const panda_file::File &pfileRef) locationMapping_[pfileRef.GetFilename()] = filename; } ASSERT(!filename.empty()); + LOG_PAOC(DEBUG) << "Starts compilation task for input file: " << filename; aotBuilder_->StartFile(filename, pfileRef.GetHeader()->checksum); } @@ -609,11 +683,9 @@ bool Paoc::TryLoadAotMethodProfile( return true; } -bool Paoc::TryLoadPandaFile(const std::string &fileName, PandaVM *vm) +bool Paoc::TryLoadCompilationTasksFromPandaFile(const std::string &fileName, PandaVM *vm) { const panda_file::File *pfile; - bool errorOccurred = false; - auto filePath = GetFilePath(fileName); if (preloadedFiles_.find(filePath) != preloadedFiles_.end()) { pfile = preloadedFiles_[filePath]; @@ -636,19 +708,95 @@ bool Paoc::TryLoadPandaFile(const std::string &fileName, PandaVM *vm) LOG_PAOC(DEBUG) << "Added panda file: " << fileName; } auto &pfileRef = *pfile; + return TryLoadCompilationTasksFromPandaFile(pfileRef); +} - if (IsAotMode()) { - StartAotFile(pfileRef); - } +bool Paoc::TryLoadCompilationTasksFromPandaFile(const panda_file::File &pfileRef) +{ + auto classes = pfileRef.GetClasses(); + bool errorOccurred = false; - if (!CompilePandaFile(pfileRef)) { - errorOccurred = true; + const std::string &fileName = pfileRef.GetFilename(); + for (auto &classId : classes) { + panda_file::File::EntityId id(classId); + ark::Class *klass = ResolveClass(pfileRef, id); + std::string className = ClassHelper::GetName(pfileRef.GetStringData(id).data); + + if (!PossibleToCompile(pfileRef, klass, id)) { + LOG_PAOC_VERBOSE << "Ignoring class `" << className << "` (id = " << id << ", file = `" << fileName << "`)"; + continue; + } + + ASSERT(klass != nullptr && klass->GetPandaFile() != nullptr); + if (!TryLoadCompilationTasksFromClass(pfileRef, klass)) { + errorOccurred = true; + PrintError("Class `" + std::move(className) + "` from " + fileName + " compiled with errors"); + if (!ShouldIgnoreFailures()) { + break; + } + } } + return !errorOccurred; +} - if (IsAotMode()) { - aotBuilder_->EndFile(); +bool Paoc::TryLoadCompilationTasksFromClass(const panda_file::File &pfileRef, Class *klass) +{ + bool errorOccurred = false; + size_t methodIndex = 0; + IterateClassMethods(pfileRef, klass, [this, &methodIndex, &pfileRef, klass, &errorOccurred](Method &method) { + if (errorOccurred && !ShouldIgnoreFailures()) { + return; + } + // NOTE(pishin, msherstennikov): revisit + // Method (or the whole class?) may already have a definition in another file, + // in this case it should not be added into AOT file. + auto methodName = runtime_->GetMethodFullName(&method, g_options.WasSetCompilerRegexWithSignature()); + auto shouldCompile = true; + const auto &curFileName = klass->GetPandaFile()->GetFullFileName(); + const auto &methodFileName = method.GetPandaFile()->GetFilename(); + // Note: pfileRef.GetFilename() and klass->GetPandaFile()->GetFilename() may be different strings + // (one is absolute path and the other is relative). + if (methodFileName != klass->GetPandaFile()->GetFilename()) { + LOG_PAOC_VERBOSE << "Ignores " << methodName << " defined in different file `" << methodFileName + << "` vs. current file `" << curFileName << "`"; + shouldCompile = false; + } else if (Skip(&method)) { + LOG_PAOC_VERBOSE << "Skips " << methodName; + shouldCompile = false; + } else if (!IsMethodNeedToBeCompiled(&method)) { + LOG_PAOC_VERBOSE << "Skips " << methodName << " which need not compile (abstract, intrinsic, native, etc.)"; + shouldCompile = false; + } else if (!IsMethodShouldBeCompiled(methodName)) { + LOG_PAOC_VERBOSE << "Skips " << methodName << " which should not compile"; + shouldCompile = false; + } else if (!g_options.MatchesRegex(methodName)) { + LOG_PAOC_VERBOSE << "Skips " << methodName << " due to regex mismatch"; + shouldCompile = false; + } + if (shouldCompile && !TryLoadCompilationTaskFromMethod(pfileRef, &method, methodIndex)) { + errorOccurred = true; + } + methodIndex++; + }); + return !errorOccurred; +} + +bool Paoc::TryLoadCompilationTaskFromMethod(const panda_file::File &pfileRef, Method *method, size_t methodIndex) +{ + if (method == nullptr) { + LOG_PAOC(WARNING) << "Method is nullptr"; + return false; } - return !errorOccurred || ShouldIgnoreFailures(); +#ifndef NDEBUG + const auto *pfile = method->GetPandaFile(); + auto methodId = method->GetFileId(); + ASSERT(pfile != nullptr); + ASSERT(!pfile->IsExternal(methodId)); +#endif + + ASSERT(IsMethodNeedToBeCompiled(method)); + compilationTasks_.emplace_back(CompilationTask {&pfileRef, method, methodIndex}); + return true; } std::unique_ptr Paoc::TryLoadZipPandaFile(const std::string &fileName) @@ -680,64 +828,110 @@ bool Paoc::CompileFiles() auto pfiles = paocOptions_->GetPaocPandaFiles(); auto *vm = ark::Runtime::GetCurrent()->GetPandaVM(); for (auto &fileName : pfiles) { - if (!TryLoadPandaFile(fileName, vm)) { + if (!TryLoadCompilationTasksFromPandaFile(fileName, vm) && !ShouldIgnoreFailures()) { return false; } } - return true; + LOG_PAOC(INFO) << "Collects " << compilationTasks_.size() << " methods to be compiled."; + if (mode_ == PaocMode::AOT) { + return ParallelRunCompilationTasks(); + } + return SequentialRunCompilationTasks(); } -std::string Paoc::GetFilePath(std::string fileName) +bool Paoc::SequentialRunCompilationTasks() { - if (runtimeOptions_->IsAotVerifyAbsPath()) { - return os::GetAbsolutePath(fileName); + bool success = true; + if (IsAotMode()) { + auto aotCtx = AotBuilderContext(this); + for (const auto &task : compilationTasks_) { + aotCtx.Proceed(task.pfile, task.method->GetClass()); + auto ctx = CompilingContext(task.method, task.methodIndex, &statisticsDump_); + success &= Compile(&ctx); + } + return success; } - return fileName; + // JIT and OSR + for (auto &task : compilationTasks_) { + auto ctx = CompilingContext(task.method, task.methodIndex, &statisticsDump_); + success &= Compile(&ctx); + } + return success; } -/** - * Compile every method from loaded panda files that matches `--compiler-regex`, - * `--paoc-skip-until`, `--paoc-compile-until` and `--paoc-methods-from-file` options: - * @return `false` on error. - */ -bool Paoc::CompilePandaFile(const panda_file::File &pfileRef) +bool Paoc::ParallelRunCompilationTasks() { - auto classes = pfileRef.GetClasses(); - bool errorOccurred = false; - for (auto &classId : classes) { - panda_file::File::EntityId id(classId); - ark::Class *klass = ResolveClass(pfileRef, id); - std::string className = ClassHelper::GetName(pfileRef.GetStringData(id).data); - - if (!PossibleToCompile(pfileRef, klass, id)) { - if (paocOptions_->IsPaocVerbose()) { - LOG_PAOC(DEBUG) << "Ignoring a class `" << className << "` (id = " << id << ", file `" - << pfileRef.GetFilename() << "`)"; - } - continue; + ASSERT(mode_ == PaocMode::AOT && "AOT mode without LLVM only."); + constexpr size_t NUM_WORKERS = 8; + bool managerStartedByPaoc = false; + if (!taskmanager::TaskManager::IsUsed()) { + LOG_PAOC(DEBUG) << "Starts TaskManager by PAOC."; + taskmanager::TaskManager::Start(NUM_WORKERS); + managerStartedByPaoc = true; + } + auto *taskQueue = taskmanager::TaskManager::CreateTaskQueue(); + auto parCtx = ParallelCompilingContext(); + auto builderCtx = AotBuilderContext(this); + + constexpr size_t MAX_NUM_TASKS_PENDING = 16; + size_t numTasksCompiled = 0; + size_t numTasks = compilationTasks_.size(); + for (; numTasksCompiled < MAX_NUM_TASKS_PENDING && numTasksCompiled < numTasks; ++numTasksCompiled) { + taskQueue->AddForegroundTask(CreateParallelCompilingTask(&parCtx, numTasksCompiled)); + } + for (size_t numTasksDone = 0; numTasksDone < numTasks; ++numTasksDone) { + auto curHandle = parCtx.PopCompiledTask(numTasksDone); + // Codegen + builderCtx.Proceed(compilationTasks_[numTasksDone].pfile, compilationTasks_[numTasksDone].method->GetClass()); + uintptr_t codeAddress = aotBuilder_->GetCurrentCodeAddress(); + curHandle->graph->GetAotData()->SetCodeOffset(codeAddress); + if (!Pipeline::RunCodegenPass(curHandle->graph)) { + LOG_PAOC(ERROR) << "Codegen() failed with task index = " << numTasksDone; } - - ASSERT(klass != nullptr); - if (paocOptions_->IsPaocVerbose()) { - LOG_PAOC(DEBUG) << "Compiling class `" << className << "` (id = " << id << ", file `" - << pfileRef.GetFilename() << "`)"; + if (!FinalizeCompileAot(curHandle.get(), codeAddress)) { + LOG_PAOC(ERROR) << "FinalizeCompileAot() failed with task index = " << numTasksDone; } - - // Check that all of the methods are compiled correctly: - ASSERT(klass->GetPandaFile() != nullptr); - if (!Compile(klass, *klass->GetPandaFile())) { - errorOccurred = true; - std::string errMsg = "Class `" + className + "` from " + pfileRef.GetFilename() + " compiled with errors"; - PrintError(errMsg); - if (!ShouldIgnoreFailures()) { - break; - } + successMethods_ += 1; + // Spawns next compilation task + if (numTasksCompiled < numTasks) { + taskQueue->AddForegroundTask(CreateParallelCompilingTask(&parCtx, numTasksCompiled++)); } + // CompilationContext inside curHandle is destroyed } + taskmanager::TaskManager::DestroyTaskQueue(taskQueue); + if (managerStartedByPaoc) { + LOG_PAOC(DEBUG) << "Ends TaskManager by PAOC."; + taskmanager::TaskManager::Finish(); + } + return true; +} - BuildClassHashTable(pfileRef); +std::function Paoc::CreateParallelCompilingTask(ParallelCompilingContext *parCtx, size_t index) +{ + const auto &curTask = compilationTasks_[index]; + auto *mainThread = Thread::GetCurrent(); + return [this, parCtx, index, mainThread, &curTask]() { + Thread::SetCurrent(mainThread); + auto ctxHandle = + std::make_unique(curTask.method, curTask.methodIndex, index, &statisticsDump_); + bool success = CompileAotWithoutCodegen(ctxHandle.get()); + if (success) { + LOG_PAOC(DEBUG) << "CompileAotWithoutCodegen() done with task index = " << index; + } else { + LOG_PAOC(ERROR) << "CompileAotWithoutCodegen() failed with task index = " << index; + } + ctxHandle->compilationStatus = success; + parCtx->SubmitCompiledTask(std::move(ctxHandle)); + LOG_PAOC(DEBUG) << "SubmitCompiledTask() done with index = " << index; + }; +} - return !errorOccurred; +std::string Paoc::GetFilePath(std::string fileName) +{ + if (runtimeOptions_->IsAotVerifyAbsPath()) { + return os::GetAbsolutePath(fileName); + } + return fileName; } ark::Class *Paoc::ResolveClass(const panda_file::File &pfileRef, panda_file::File::EntityId classId) @@ -793,108 +987,64 @@ bool Paoc::PossibleToCompile(const panda_file::File &pfileRef, const ark::Class return true; } -/** - * Compile the class. - * @return `false` on error. - */ -bool Paoc::Compile(Class *klass, const panda_file::File &pfileRef) +bool Paoc::CompileInGraph(CompilingContext *ctx, std::string methodName, bool isOsr) { - ASSERT(klass != nullptr); - - if (IsAotMode()) { - aotBuilder_->StartClass(*klass); - } - bool errorOccurred = false; - size_t methodIndex = 0; - IterateClassMethods(pfileRef, klass, [this, &methodIndex, &pfileRef, &errorOccurred](Method &method) { - if (errorOccurred && !ShouldIgnoreFailures()) { - return; - } - // NOTE(pishin, msherstennikov): revisit - // Method (or the whole class?) may already have a definition in another file, - // in this case it should not be added into AOT file. - auto methodName = runtime_->GetMethodFullName(&method, g_options.WasSetCompilerRegexWithSignature()); - if (method.GetPandaFile()->GetFilename() == pfileRef.GetFilename() && !Skip(&method) && - IsMethodShouldBeCompiled(methodName) && g_options.MatchesRegex(methodName) && - !Compile(&method, methodIndex)) { - errorOccurred = true; - } - methodIndex++; - }); - - if (IsAotMode()) { - aotBuilder_->EndClass(); - } + compiler::InPlaceCompilerTaskRunner taskRunner; + auto &taskCtx = taskRunner.GetContext(); + taskCtx.SetMethod(ctx->method); + taskCtx.SetOsr(isOsr); + taskCtx.SetAllocator(&ctx->allocator); + taskCtx.SetLocalAllocator(&ctx->graphLocalAllocator); + taskCtx.SetMethodName(std::move(methodName)); + taskRunner.AddFinalize( + [&graph = ctx->graph](InPlaceCompilerContext &compilerCtx) { graph = compilerCtx.GetGraph(); }); - return !errorOccurred; + bool success = true; + taskRunner.AddCallbackOnFail([&success]([[maybe_unused]] InPlaceCompilerContext &compilerCtx) { success = false; }); + auto arch = ChooseArch(Arch::NONE); + bool isDynamic = ark::panda_file::IsDynamicLanguage(ctx->method->GetClass()->GetSourceLang()); + compiler::CompileInGraph(runtime_, isDynamic, arch, std::move(taskRunner)); + return success; } -bool Paoc::Compile(Method *method, size_t methodIndex) +bool Paoc::Compile(CompilingContext *ctx) { - if (method == nullptr) { - LOG_PAOC(WARNING) << "Method is nullptr"; - return false; - } -#ifndef NDEBUG - const auto *pfile = method->GetPandaFile(); - auto methodId = method->GetFileId(); - ASSERT(pfile != nullptr); - ASSERT(!pfile->IsExternal(methodId)); -#endif - - if (method->IsAbstract() || method->IsNative() || method->IsIntrinsic()) { - return true; - } + auto *method = ctx->method; auto methodName = runtime_->GetMethodFullName(method, false); - ++compilationIndex_; LOG_PAOC(INFO) << "[" << compilationIndex_ << "] Compile method (id=" << method->GetFileId() << "): " << methodName; - CompilingContext ctx(method, methodIndex, &statisticsDump_); - PaocClusters::ScopedApplySpecialOptions to(methodName, &clustersInfo_); switch (mode_) { case PaocMode::AOT: case PaocMode::LLVM: - if (!CompileAot(&ctx)) { - EVENT_COMPILATION(methodName, false, ctx.method->GetCodeSize(), 0, 0, 0, + if (!CompileAot(ctx)) { + EVENT_COMPILATION(methodName, false, ctx->method->GetCodeSize(), 0, 0, 0, events::CompilationStatus::FAILED); failedMethods_++; - ctx.compilationStatus = false; + ctx->compilationStatus = false; } else { successMethods_++; + ctx->compilationStatus = true; } break; case PaocMode::JIT: - ctx.compilationStatus = CompileJit(&ctx); + ctx->compilationStatus = CompileJit(ctx); break; case PaocMode::OSR: - ctx.compilationStatus = CompileOsr(&ctx); + ctx->compilationStatus = CompileOsr(ctx); break; default: UNREACHABLE(); } - return ctx.compilationStatus; -} - -bool Paoc::CompileInGraph(CompilingContext *ctx, std::string methodName, bool isOsr) -{ - compiler::InPlaceCompilerTaskRunner taskRunner; - auto &taskCtx = taskRunner.GetContext(); - taskCtx.SetMethod(ctx->method); - taskCtx.SetOsr(isOsr); - taskCtx.SetAllocator(&ctx->allocator); - taskCtx.SetLocalAllocator(&ctx->graphLocalAllocator); - taskCtx.SetMethodName(std::move(methodName)); - taskRunner.AddFinalize( - [&graph = ctx->graph](InPlaceCompilerContext &compilerCtx) { graph = compilerCtx.GetGraph(); }); - - bool success = true; - taskRunner.AddCallbackOnFail([&success]([[maybe_unused]] InPlaceCompilerContext &compilerCtx) { success = false; }); - auto arch = ChooseArch(Arch::NONE); - bool isDynamic = ark::panda_file::IsDynamicLanguage(ctx->method->GetClass()->GetSourceLang()); - compiler::CompileInGraph(runtime_, isDynamic, arch, std::move(taskRunner)); - return success; + if (!ctx->compilationStatus) { + if (!ShouldIgnoreFailures()) { + LOG_PAOC(FATAL) << "Failed to compile method: " << method->GetFullName(); + } + LOG_PAOC(ERROR) << "Failed to compile method: " << method->GetFullName(); + return false; + } + return true; } /** @@ -951,7 +1101,8 @@ bool Paoc::TryCreateGraph(CompilingContext *ctx) bool Paoc::FinalizeCompileAot(CompilingContext *ctx, [[maybe_unused]] uintptr_t codeAddress) { - CompiledMethod compiledMethod(ctx->graph->GetArch(), ctx->method, ctx->index); + ASSERT(ctx->graph != nullptr); + CompiledMethod compiledMethod(ctx->graph->GetArch(), ctx->method, ctx->methodIndex); compiledMethod.SetCode(ctx->graph->GetCode().ToConst()); compiledMethod.SetCodeInfo(ctx->graph->GetCodeInfoData()); #ifdef PANDA_COMPILER_DEBUG_INFO @@ -964,7 +1115,6 @@ bool Paoc::FinalizeCompileAot(CompilingContext *ctx, [[maybe_unused]] uintptr_t LOG(INFO, COMPILER) << "Ark AOT successfully compiled method: " << runtime_->GetMethodFullName(ctx->method, false); EVENT_PAOC("Compiling " + runtime_->GetMethodFullName(ctx->method, false) + " using panda"); - ASSERT(ctx->graph != nullptr); aotBuilder_->AddMethod(compiledMethod); @@ -974,14 +1124,14 @@ bool Paoc::FinalizeCompileAot(CompilingContext *ctx, [[maybe_unused]] uintptr_t return true; } -bool Paoc::RunOptimizations(CompilingContext *ctx) +bool Paoc::RunOptimizations(CompilingContext *ctx, bool skipsCodegen) { compiler::InPlaceCompilerTaskRunner taskRunner; taskRunner.GetContext().SetGraph(ctx->graph); bool success = true; taskRunner.AddCallbackOnFail([&success]([[maybe_unused]] InPlaceCompilerContext &compilerCtx) { success = false; }); - compiler::RunOptimizations(std::move(taskRunner)); + compiler::RunOptimizations(std::move(taskRunner), skipsCodegen); return success; } @@ -1043,6 +1193,43 @@ bool Paoc::CompileAot(CompilingContext *ctx) return FinalizeCompileAot(ctx, codeAddress); } +bool Paoc::CompileAotWithoutCodegen(CompilingContext *ctx) +{ + ASSERT(ctx != nullptr); + ASSERT(mode_ == PaocMode::AOT && "AOT without LLVM only."); + + auto *method = ctx->method; + auto methodName = runtime_->GetMethodFullName(method, false); + ++compilationIndex_; + ATOMIC_FETCH_ADD(&compilationIndex_, 1, memory_order_relaxed); + LOG_PAOC(INFO) << "[" << compilationIndex_ << "] Compile method (id=" << method->GetFileId() << "): " << methodName; + + PaocClusters::ScopedApplySpecialOptions to(methodName, &clustersInfo_); + + std::string className = ClassHelper::GetName(ctx->method->GetClassName().data); + if (runtimeOptions_->WasSetEventsOutput()) { + EVENT_PAOC("Trying to compile method: " + className + + "::" + reinterpret_cast(ctx->method->GetName().data)); + } + + if (!TryCreateGraph(ctx)) { + PrintError("Graph creation failed!"); + return false; + } + constexpr uintptr_t DUMMY_CODE_OFFSET = 0; + MakeAotData(ctx, DUMMY_CODE_OFFSET); + if (!ctx->graph->RunPass()) { + PrintError("IrBuilder failed!"); + return false; + } + constexpr bool SKIPS_CODEGEN = true; + if (!RunOptimizations(ctx, SKIPS_CODEGEN)) { + PrintError("RunOptimizations failed!"); + return false; + } + return true; +} + void Paoc::MakeAotData(CompilingContext *ctx, uintptr_t codeAddress) { auto *aotData = ctx->graph->GetAllocator()->New( @@ -1096,6 +1283,11 @@ void Paoc::PrintUsage(const ark::PandArgParser &paParser) std::cerr << paParser.GetHelpString() << std::endl; } +bool Paoc::IsMethodNeedToBeCompiled(const Method *method) +{ + return !method->IsAbstract() && !method->IsNative() && !method->IsIntrinsic(); +} + bool Paoc::IsMethodShouldBeCompiled(const std::string &methodFullName) { if (paocOptions_->IsPaocMethodsFromFileIswhite()) { diff --git a/static_core/compiler/tools/paoc/paoc.h b/static_core/compiler/tools/paoc/paoc.h index a05b48627a..6b5962678a 100644 --- a/static_core/compiler/tools/paoc/paoc.h +++ b/static_core/compiler/tools/paoc/paoc.h @@ -50,6 +50,7 @@ protected: NO_COPY_SEMANTIC(CompilingContext); NO_MOVE_SEMANTIC(CompilingContext); CompilingContext(Method *methodPtr, size_t methodIndex, std::ofstream *statisticsDump); + CompilingContext(Method *methodPtr, size_t methodIndex, size_t taskIndex, std::ofstream *statisticsDump); ~CompilingContext(); void DumpStatistics() const; @@ -58,11 +59,61 @@ protected: ark::ArenaAllocator allocator; // NOLINT(misc-non-private-member-variables-in-classes) ark::ArenaAllocator graphLocalAllocator; // NOLINT(misc-non-private-member-variables-in-classes) ark::compiler::Graph *graph {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes) - size_t index; // NOLINT(misc-non-private-member-variables-in-classes) + size_t methodIndex; // NOLINT(misc-non-private-member-variables-in-classes) + size_t taskIndex; // NOLINT(misc-non-private-member-variables-in-classes) std::ofstream *stats {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes) bool compilationStatus {true}; // NOLINT(misc-non-private-member-variables-in-classes) }; + struct CompilationTask { + const panda_file::File *pfile; + Method *method; + size_t methodIndex; + }; + + class ParallelCompilingContext { + public: + using TaskContextHandle = std::unique_ptr; + + NO_COPY_SEMANTIC(ParallelCompilingContext); + NO_MOVE_SEMANTIC(ParallelCompilingContext); + ParallelCompilingContext() = default; + ~ParallelCompilingContext() = default; + + void SubmitCompiledTask(TaskContextHandle &&task); + TaskContextHandle PopCompiledTask(size_t index); + + private: + struct HandleComparator { + bool operator()(const TaskContextHandle &lhs, const TaskContextHandle &rhs) const + { + return lhs->taskIndex < rhs->taskIndex; + } + }; + + std::set submittedTasks_; + os::memory::Mutex submissionMutex_; + os::memory::ConditionVariable aotBuilderCv_; + }; + + class AotBuilderContext { + public: + explicit AotBuilderContext(Paoc *self) : self_(self) {} + ~AotBuilderContext(); + NO_COPY_SEMANTIC(AotBuilderContext); + NO_MOVE_SEMANTIC(AotBuilderContext); + + void Proceed(const panda_file::File *pfile, Class *klass); + + private: + void EndCurrentClass(); + void EndCurrentFile(); + + Paoc *self_ {nullptr}; + const panda_file::File *curFile_ {nullptr}; + Class *curClass_ {nullptr}; + }; + virtual std::unique_ptr CreateAotBuilder() { return std::make_unique(); @@ -72,7 +123,15 @@ private: void RunAotMode(const ark::Span &args); void StartAotFile(const panda_file::File &pfileRef); bool CompileFiles(); - bool TryLoadPandaFile(const std::string &fileName, PandaVM *vm); + bool TryLoadCompilationTasksFromPandaFile(const std::string &fileName, PandaVM *vm); + bool TryLoadCompilationTasksFromPandaFile(const panda_file::File &pfileRef); + bool TryLoadCompilationTasksFromClass(const panda_file::File &pfileRef, Class *klass); + bool TryLoadCompilationTaskFromMethod(const panda_file::File &pfileRef, Method *method, size_t methodIndex); + bool SequentialRunCompilationTasks(); + bool ParallelRunCompilationTasks(); + + std::function CreateParallelCompilingTask(ParallelCompilingContext *parCtx, size_t index); + std::unique_ptr TryLoadZipPandaFile(const std::string &fileName); bool TryLoadAotProfile(); bool TryLoadAotFileProfile(ProfilingLoader &profilingLoader, const panda_file::File &pfileRef, size_t pfileIdx); @@ -80,22 +139,21 @@ private: PandaMap &methodProfiles, uint32_t classId, Method &method); std::string BuildClassContext(); - bool CompilePandaFile(const panda_file::File &pfileRef); ark::Class *ResolveClass(const panda_file::File &pfileRef, panda_file::File::EntityId classId); bool PossibleToCompile(const panda_file::File &pfileRef, const ark::Class *klass, panda_file::File::EntityId classId); - bool Compile(Class *klass, const panda_file::File &pfileRef); - - bool Compile(Method *method, size_t methodIndex); bool CompileInGraph(CompilingContext *ctx, std::string methodName, bool isOsr); - bool RunOptimizations(CompilingContext *ctx); + bool RunOptimizations(CompilingContext *ctx, bool skipsCodegen = false); + bool Compile(CompilingContext *ctx); bool CompileJit(CompilingContext *ctx); bool CompileOsr(CompilingContext *ctx); bool CompileAot(CompilingContext *ctx); + bool CompileAotWithoutCodegen(CompilingContext *ctx); void MakeAotData(CompilingContext *ctx, uintptr_t codeAddress); bool FinalizeCompileAot(CompilingContext *ctx, [[maybe_unused]] uintptr_t codeAddress); void PrintError(const std::string &error); void PrintUsage(const ark::PandArgParser &paParser); + bool IsMethodNeedToBeCompiled(const Method *method); bool IsMethodShouldBeCompiled(const std::string &methodFullName); bool Skip(Method *method); static std::string GetFileLocation(const panda_file::File &pfileRef, std::string location); @@ -170,7 +228,8 @@ private: std::set methodsList_; std::unordered_map locationMapping_; std::unordered_map preloadedFiles_; - size_t compilationIndex_ {0}; + std::vector compilationTasks_; + std::atomic_size_t compilationIndex_ {0}; SkipInfo skipInfo_ {false, false}; PaocClusters clustersInfo_; diff --git a/static_core/compiler/tools/paoc/paoc_llvm.cpp b/static_core/compiler/tools/paoc/paoc_llvm.cpp index dacd9096d8..1fb0fd7439 100644 --- a/static_core/compiler/tools/paoc/paoc_llvm.cpp +++ b/static_core/compiler/tools/paoc/paoc_llvm.cpp @@ -37,7 +37,7 @@ Paoc::LLVMCompilerStatus PaocLLVM::TryLLVM(CompilingContext *ctx) auto result = llvmAotCompiler_->TryAddGraph(ctx->graph); if (result.HasValue()) { if (result.Value()) { - GetAotBuilder()->AddMethodHeader(ctx->method, ctx->index); + GetAotBuilder()->AddMethodHeader(ctx->method, ctx->methodIndex); return LLVMCompilerStatus::COMPILED; } // In result.Value() == false case (e.g. unbalanced monitors), fallthrough to possible fallback below } else if (!llvmbackend::g_options.IsLlvmAllowBreakage() || !ShouldIgnoreFailures()) { diff --git a/static_core/docs/task_manager.md b/static_core/docs/task_manager.md index c5020a4e90..797338d315 100644 --- a/static_core/docs/task_manager.md +++ b/static_core/docs/task_manager.md @@ -6,7 +6,7 @@ For Hybrid mode (i.e. we can execute both static and dynamic code) TaskManager a # Implementation details -##Task +## Task It is some limited by time task, which has these properties: - priority of operation: `background` or `foreground`; @@ -16,17 +16,17 @@ It is some limited by time task, which has these properties: The time is required to finish the task should be limited by some reasonable value, to make the whole system with Task management optimal. -##WorkerThread +## WorkerThread WorkerThread is the thread which executing tasks. Each WorkerThread has two queues - one for the foreground tasks and one for the background tasks. WorkerThread always try to execute task from the foreground queue first, if it is empty, then it try to execute task from the background queue. If no tasks in both queues - WorkerThread request `TaskManager` for more tasks. -##TaskManager +## TaskManager Is responsible for tasks "scheduling". I.e. each `WorkerThread` request `TaskManager` for new tasks. TaskManager creates array of tasks in proportion based on the current context(i.e. which language currently executed - static or dynamic, do we expect GC soon or not, etc). TaskManager make decision about scheduling based on some state of the system. The state of the system is provided by changing priority for TaskQueue(s). For example if we are currently expect a lot of GC because we have a lot of allocations, we will increase priority for TaskQueue for GC tasks. TaskManager choose more tasks from TaskQueues with higher priority. First tasks with `foreground` priority are selected in proportion based on TaskQueues priority, then if there are tasks with `foreground` priority in some TaskQueues they are selected without priority/proportion rules, if not - `background` tasks will be selected in proportion based on TasqQueues priority. -##TaskQueue +## TaskQueue It is a queue for tasks of the same "kind" or "components" (for example "JIT") which is fullfilled by corresponding components of VM. diff --git a/static_core/libpandabase/tests/taskmanager/task_scheduler_test.cpp b/static_core/libpandabase/tests/taskmanager/task_scheduler_test.cpp index 515125f637..bc20e70fcb 100644 --- a/static_core/libpandabase/tests/taskmanager/task_scheduler_test.cpp +++ b/static_core/libpandabase/tests/taskmanager/task_scheduler_test.cpp @@ -303,6 +303,9 @@ TEST_F(TaskSchedulerTest, TaskCreateTaskRecursively) constexpr size_t COUNT_OF_REPLICAS = 6U; constexpr size_t MAX_RECURSION_DEPTH = 5U; std::function runner; + // Let F(r) be the counter increment with recursionDepth = r, then + // F(r) = COUNT_OF_REPLICAS * F(r + 1) + 1 + // F(4) = 1, F(3) = 7, F(2) = 43, F(1) = 259, F(0) = 1555 runner = [&counter, &runner, &gcQueue](size_t recursionDepth) { if (recursionDepth < MAX_RECURSION_DEPTH) { for (size_t j = 0; j < COUNT_OF_REPLICAS; j++) { @@ -318,6 +321,8 @@ TEST_F(TaskSchedulerTest, TaskCreateTaskRecursively) } gcQueue->WaitTasks(); ASSERT_TRUE(gcQueue->IsEmpty()); + constexpr size_t EXPECTED_COUNTER_INCREMENT_PER_TASK = 1555; + ASSERT_EQ(COUNT_OF_TASK * EXPECTED_COUNTER_INCREMENT_PER_TASK, counter); TaskManager::DestroyTaskQueue(gcQueue); TaskManager::Finish(); } diff --git a/static_core/runtime/class_linker.cpp b/static_core/runtime/class_linker.cpp index 8fcbfe49bb..82cae20aa0 100644 --- a/static_core/runtime/class_linker.cpp +++ b/static_core/runtime/class_linker.cpp @@ -1404,8 +1404,6 @@ Class *ClassLinker::GetClass(const uint8_t *descriptor, bool needCopyDescriptor, { ASSERT(context != nullptr); ASSERT(descriptor != nullptr); - ASSERT(!MTManagedThread::ThreadIsMTManagedThread(Thread::GetCurrent()) || - !PandaVM::GetCurrent()->GetGC()->IsGCRunning() || PandaVM::GetCurrent()->GetMutatorLock()->HasLock()); Class *cls = FindLoadedClass(descriptor, context); if (cls != nullptr) { @@ -1453,8 +1451,6 @@ Class *ClassLinker::GetClass(const panda_file::File &pf, panda_file::File::Entit ClassLinkerErrorHandler *errorHandler /* = nullptr */) { ASSERT(context != nullptr); - ASSERT(!MTManagedThread::ThreadIsMTManagedThread(Thread::GetCurrent()) || - !PandaVM::GetCurrent()->GetGC()->IsGCRunning() || PandaVM::GetCurrent()->GetMutatorLock()->HasLock()); Class *cls = pf.GetPandaCache()->GetClassFromCache(id); if (cls != nullptr) { diff --git a/static_core/runtime/locks.cpp b/static_core/runtime/locks.cpp index f9801a0503..23ea89ed6e 100644 --- a/static_core/runtime/locks.cpp +++ b/static_core/runtime/locks.cpp @@ -56,9 +56,6 @@ MutatorLock *Locks::NewMutatorLock() void MutatorLock::ReadLock() { -#ifndef ARK_HYBRID - ASSERT(!HasLock()); -#endif LockT::ReadLock(); LOG(DEBUG, RUNTIME) << "MutatorLock::ReadLock"; Thread::GetCurrent()->SetLockState(RDLOCK); @@ -66,9 +63,6 @@ void MutatorLock::ReadLock() void MutatorLock::WriteLock() { -#ifndef ARK_HYBRID - ASSERT(!HasLock()); -#endif LockT::WriteLock(); LOG(DEBUG, RUNTIME) << "MutatorLock::WriteLock"; Thread::GetCurrent()->SetLockState(WRLOCK); @@ -96,9 +90,6 @@ bool MutatorLock::TryWriteLock() void MutatorLock::Unlock() { -#ifndef ARK_HYBRID - ASSERT(HasLock()); -#endif LockT::Unlock(); LOG(DEBUG, RUNTIME) << "MutatorLock::Unlock"; Thread::GetCurrent()->SetLockState(UNLOCKED); diff --git a/static_core/runtime/mem/heap_manager.cpp b/static_core/runtime/mem/heap_manager.cpp index 3523092bbf..61128e836f 100644 --- a/static_core/runtime/mem/heap_manager.cpp +++ b/static_core/runtime/mem/heap_manager.cpp @@ -108,7 +108,6 @@ ObjectHeader *HeapManager::AllocateObject(BaseClass *cls, size_t size, Alignment ObjectAllocatorBase::ObjMemInitPolicy objInitType, bool pinned) { ASSERT(size >= ObjectHeader::ObjectHeaderSize()); - ASSERT(GetGC()->IsMutatorAllowed()); ASSERT(cls != nullptr); TriggerGCIfNeeded(); if (thread == nullptr) { @@ -218,7 +217,6 @@ ObjectHeader *HeapManager::AllocateNonMovableObject(BaseClass *cls, size_t size, ObjectAllocatorBase::ObjMemInitPolicy objInitType) { ASSERT(size >= ObjectHeader::ObjectHeaderSize()); - ASSERT(GetGC()->IsMutatorAllowed()); TriggerGCIfNeeded(); void *mem = objectAllocator_.AsObjectAllocator()->AllocateNonMovable(size, align, thread, objInitType); if (UNLIKELY(mem == nullptr)) { @@ -259,7 +257,6 @@ ObjectHeader *HeapManager::AllocateNonMovableObject(BaseClass *cls, size_t size, ObjectHeader *HeapManager::InitObjectHeaderAtMem(BaseClass *cls, void *mem) { ASSERT(mem != nullptr); - ASSERT(GetGC()->IsMutatorAllowed()); auto object = static_cast(mem); // we need zeroed memory here according to ISA @@ -279,14 +276,12 @@ void HeapManager::TriggerGCIfNeeded() Frame *HeapManager::AllocateExtFrame(size_t size, size_t extSz) { - ASSERT(GetGC()->IsMutatorAllowed()); StackFrameAllocator *frameAllocator = GetCurrentStackFrameAllocator(); return Frame::FromExt(frameAllocator->Alloc(size), extSz); } bool HeapManager::CreateNewTLAB(ManagedThread *thread) { - ASSERT(GetGC()->IsMutatorAllowed()); ASSERT(thread != nullptr); size_t newTlabSize = 0; TLAB *oldTlab = thread->GetTLAB(); @@ -319,7 +314,6 @@ void HeapManager::RegisterTLAB(const TLAB *tlab) void HeapManager::FreeExtFrame(Frame *frame, size_t extSz) { - ASSERT(GetGC()->IsMutatorAllowed()); StackFrameAllocator *frameAllocator = GetCurrentStackFrameAllocator(); frameAllocator->Free(Frame::ToExt(frame, extSz)); } diff --git a/static_core/tests/checked/CMakeLists.txt b/static_core/tests/checked/CMakeLists.txt index 414906c65a..48f2e1aa72 100644 --- a/static_core/tests/checked/CMakeLists.txt +++ b/static_core/tests/checked/CMakeLists.txt @@ -221,7 +221,6 @@ panda_add_checked_test(FILE ${CMAKE_CURRENT_SOURCE_DIR}/disasm_and_log_demo.pa) if (PANDA_COMPILER_TARGET_AARCH64 AND PANDA_COMPILER_TARGET_AARCH32) panda_add_checked_test(FILE ${CMAKE_CURRENT_SOURCE_DIR}/cross_peephole.pa) endif() -panda_add_checked_test(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ifcvt.pa) if (PANDA_COMPILER_TARGET_AARCH64) panda_add_checked_test(FILE ${CMAKE_CURRENT_SOURCE_DIR}/ifcvt_float.pa) panda_add_checked_test(FILE ${CMAKE_CURRENT_SOURCE_DIR}/cleanup_sso.pa) -- Gitee