diff --git a/ecmascript/compiler/aot_file/aot_file_info.cpp b/ecmascript/compiler/aot_file/aot_file_info.cpp index abf2929d118f66f86131e7e32661d3d4811a26d4..a3a242023b0e8846f09908f8896dc7cb5679e87a 100644 --- a/ecmascript/compiler/aot_file/aot_file_info.cpp +++ b/ecmascript/compiler/aot_file/aot_file_info.cpp @@ -16,6 +16,9 @@ #include "ecmascript/compiler/aot_file/aot_file_info.h" namespace panda::ecmascript { + +ConcurrentMonitor ConcurrentMonitor::monitor_; + void AOTFileInfo::Destroy() { entryNum_ = 0; diff --git a/ecmascript/compiler/aot_file/aot_file_info.h b/ecmascript/compiler/aot_file/aot_file_info.h index e42fbc87b5cbcf82b94d76f1401180dcdd1106f4..4db97e07f87bedee4bd2f9945795f467f6c23314 100644 --- a/ecmascript/compiler/aot_file/aot_file_info.h +++ b/ecmascript/compiler/aot_file/aot_file_info.h @@ -24,6 +24,55 @@ #include "ecmascript/stackmap/ark_stackmap.h" namespace panda::ecmascript { +class PUBLIC_API ConcurrentMonitor { +public: + void RegisterThread() + { + std::lock_guard lock(mtx_); + ++registeredThreads_; + } + + void UnregisterThread() + { + std::unique_lock lock(mtx_); + --registeredThreads_; + if (waitingThreads_ == registeredThreads_) + { + // 如果刚好等够了,放行 + ++generation_; + waitingThreads_ = 0; + cv_.notify_all(); + } + } + + void ArriveAndWait() + { + std::unique_lock lock(mtx_); + if (registeredThreads_ == 0) { + return; + } + int gen = generation_; + ++waitingThreads_; + if (waitingThreads_ == registeredThreads_) { + ++generation_; + waitingThreads_ = 0; + cv_.notify_all(); + } else { + // 等待其他线程 + cv_.wait(lock, [&] { + return gen != generation_; + }); + } + } + static ConcurrentMonitor monitor_; +private: + std::mutex mtx_; + std::condition_variable cv_; + int registeredThreads_ = 0; + int waitingThreads_ = 0; + int generation_ = 0; +}; + class PUBLIC_API AOTFileInfo { public: using FuncEntryDes = ecmascript::FuncEntryDes; diff --git a/ecmascript/compiler/code_generator.h b/ecmascript/compiler/code_generator.h index 5d871ee8bad00d7c38762b83ce3a40d44391263c..54cc0174b01ff9f92ffd752d34890c7b207aa3ac 100644 --- a/ecmascript/compiler/code_generator.h +++ b/ecmascript/compiler/code_generator.h @@ -85,6 +85,8 @@ struct CodeInfo { uint8_t *AllocaCodeSectionOnDemand(uintptr_t size, const char *sectionName); + void VerifyAddress(uintptr_t addr, uintptr_t size, uintptr_t alignSize); + uint8_t *AllocaDataSectionImp(uintptr_t size, const char *sectionName, AllocaSectionCallback allocaInReqSecBuffer, AllocaSectionCallback allocaInNotReqSecBuffer); @@ -137,6 +139,8 @@ private: CodeSpaceOnDemand &codeSpaceOnDemand_; bool useOwnSpace_ {false}; std::unique_ptr ownCodeSpace_ {nullptr}; + uintptr_t lastAddr_ {0}; + uintptr_t lastSize_ {0}; }; class Assembler { diff --git a/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp b/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp index 7d478c4d40e16760edb185621d704ff3f9887f51..318655f244141a37b3c48bda5eac2f89320dc11e 100644 --- a/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp +++ b/ecmascript/compiler/codegen/llvm/llvm_codegen.cpp @@ -105,14 +105,14 @@ CodeInfo::CodeSpace::~CodeSpace() uint8_t *CodeInfo::CodeSpace::Alloca(uintptr_t size, bool isReq, size_t alignSize) { - LockHolder lock(mutex_); +#ifndef NDEBUG + ConcurrentMonitor::monitor_.ArriveAndWait(); +#endif uint8_t *addr = nullptr; auto bufBegin = isReq ? reqSecs_ : unreqSecs_; auto &curPos = isReq ? reqBufPos_ : unreqBufPos_; size_t limit = isReq ? REQUIRED_SECS_LIMIT : UNREQUIRED_SECS_LIMIT; if (curPos + size > limit) { - LOG_COMPILER(ERROR) << std::hex << "Alloca Section failed. Current curPos:" << curPos - << " plus size:" << size << "exceed limit:" << limit; exit(-1); } if (alignSize > 0) { @@ -182,11 +182,14 @@ uint8_t *CodeInfo::AllocaCodeSectionImp(uintptr_t size, const char *sectionName, if (!alreadyPageAlign_) { addr = (this->*allocaInReqSecBuffer)(size, AOTFileInfo::PAGE_ALIGN); alreadyPageAlign_ = true; + VerifyAddress(reinterpret_cast(addr), size, AOTFileInfo::PAGE_ALIGN); } else { addr = (this->*allocaInReqSecBuffer)(size, AOTFileInfo::TEXT_SEC_ALIGN); + VerifyAddress(reinterpret_cast(addr), size, AOTFileInfo::TEXT_SEC_ALIGN); } } else { addr = (this->*allocaInReqSecBuffer)(size, 0); + VerifyAddress(reinterpret_cast(addr), size, 0); } codeInfo_.push_back({addr, size}); if (curSec.isValidAOTSec()) { @@ -205,6 +208,25 @@ uint8_t *CodeInfo::AllocaCodeSectionOnDemand(uintptr_t size, const char *section return AllocaCodeSectionImp(size, sectionName, &CodeInfo::AllocaOnDemand); } +void CodeInfo::VerifyAddress(uintptr_t addr, uintptr_t size, uintptr_t alignSize) +{ + if (lastAddr_ == 0) { + lastAddr_ = addr; + lastSize_ = size; + return; + } + uintptr_t expectAddr = lastAddr_ + lastSize_; + if (alignSize != 0 && !IsAligned(expectAddr, alignSize)) { + expectAddr = AlignUp(expectAddr, alignSize); + } + if (expectAddr != addr) { + LOG_COMPILER(FATAL) << "VerifyAddress failed: " << lastAddr_ << " " << lastSize_ << " " << alignSize << + ", addr: " << addr; + } + lastAddr_ = addr; + lastSize_ = size; +} + uint8_t *CodeInfo::AllocaDataSectionImp(uintptr_t size, const char *sectionName, AllocaSectionCallback allocaInReqSecBuffer, AllocaSectionCallback allocaInNotReqSecBuffer) diff --git a/ecmascript/compiler/file_generators.cpp b/ecmascript/compiler/file_generators.cpp index b67588743d1d8b954848dd59f3e9e027d69c39cb..22d8991039fa32a6e8c08008182546d061337da2 100644 --- a/ecmascript/compiler/file_generators.cpp +++ b/ecmascript/compiler/file_generators.cpp @@ -377,10 +377,14 @@ void StubFileGenerator::CollectCodeInfo() std::vector threads; for (size_t i = 1; i < modulePackage_.size(); ++i) { threads.emplace_back([&, i]() { + ConcurrentMonitor::monitor_.RegisterThread(); entryPoints[i] = modulePackage_[i].GetFuncEntryPoints(); + ConcurrentMonitor::monitor_.UnregisterThread(); }); } + ConcurrentMonitor::monitor_.RegisterThread(); entryPoints[0] = modulePackage_[0].GetFuncEntryPoints(); + ConcurrentMonitor::monitor_.UnregisterThread(); for (auto& t : threads) { if (t.joinable()) { t.join(); @@ -533,10 +537,14 @@ void StubFileGenerator::RunLLVMAssembler() for (size_t i = 1; i < modulePackage_.size(); ++i) { const CompilerLog &log = *(this->log_); threads.emplace_back([&, i] { + ConcurrentMonitor::monitor_.RegisterThread(); modulePackage_[i].RunAssembler(log, false); + ConcurrentMonitor::monitor_.UnregisterThread(); }); } + ConcurrentMonitor::monitor_.RegisterThread(); modulePackage_[0].RunAssembler(*(this->log_), false); + ConcurrentMonitor::monitor_.UnregisterThread(); for (auto& t : threads) { if (t.joinable()) { t.join(); diff --git a/ecmascript/tests/machine_code_test.cpp b/ecmascript/tests/machine_code_test.cpp index fcbaa557f7156445920a9d87384deb5ee39ef7f8..b7801b706102a6bddccee21238993f35c80c8f57 100644 --- a/ecmascript/tests/machine_code_test.cpp +++ b/ecmascript/tests/machine_code_test.cpp @@ -22,7 +22,9 @@ #include "ecmascript/js_array.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/object_factory-inl.h" +#include "ecmascript/compiler/aot_file/aot_file_info.h" #include "ecmascript/tests/test_helper.h" +#include using namespace panda; using namespace panda::ecmascript; @@ -226,4 +228,27 @@ HWTEST_F_L0(MachineCodeTest, SetText003) Jit::GetInstance()->SetEnableAsyncCopyToFort(true); } +HWTEST_F_L0(MachineCodeTest, ConcurrentTest001) +{ + std::vector threads; + for (size_t i = 1; i < 10; ++i) { + threads.emplace_back([] { + ConcurrentMonitor::monitor_.RegisterThread(); + sleep(1); + ConcurrentMonitor::monitor_.ArriveAndWait(); + sleep(1); + ConcurrentMonitor::monitor_.UnregisterThread(); + }); + } + ConcurrentMonitor::monitor_.RegisterThread(); + sleep(1); + ConcurrentMonitor::monitor_.ArriveAndWait(); + sleep(1); + ConcurrentMonitor::monitor_.UnregisterThread(); + for (auto &t: threads) { + if (t.joinable()) { + t.join(); + } + } +} } diff --git a/libark_jsruntime.map b/libark_jsruntime.map index ff2b0e3c7aaef854b0ec614509d342c9f3345892..667bb92949ff1d17b7f853a3063f6b444a7f3a0e 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -19,7 +19,7 @@ panda::ecmascript::COMPILER_HELP_HEAD_MSG*; panda::ecmascript::g_isEnableCMCGC*; panda::ArkCrashHolder*; - + panda::ecmascript::ConcurrentMonitor::*; panda::ArrayBufferRef::*; panda::SendableArrayBufferRef::*; panda::BufferRef::*;