From cce6193d40ef7314c6a2cbc6f72c3c26e0420ca7 Mon Sep 17 00:00:00 2001 From: quiet-thought Date: Tue, 15 Jul 2025 14:16:18 +0800 Subject: [PATCH] Fix multi-context module memory leak Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICLVEF Signed-off-by: quiet-thought Change-Id: I90f5b4df6a792f695e4515db48fa016a21510b71 --- ecmascript/dfx/hprof/tests/hprof_test.cpp | 4 +- ecmascript/ecma_vm.cpp | 37 +++--- ecmascript/ecma_vm.h | 9 +- ecmascript/js_thread.cpp | 1 + .../jspandafile/js_pandafile_manager.cpp | 20 ++- ecmascript/jspandafile/js_pandafile_manager.h | 6 + ecmascript/mem/assert_scope.cpp | 21 +++- ecmascript/mem/assert_scope.h | 13 ++ ecmascript/module/js_module_deregister.cpp | 34 +++-- ecmascript/module/js_module_deregister.h | 6 +- ecmascript/module/js_module_manager.cpp | 29 ++++- ecmascript/module/js_module_manager.h | 21 ++++ ecmascript/module/js_module_namespace.cpp | 19 ++- ecmascript/module/js_module_namespace.h | 7 ++ ecmascript/module/js_module_source_text.cpp | 12 +- ecmascript/module/js_module_source_text.h | 2 + .../module/js_shared_module_manager.cpp | 9 +- ecmascript/module/js_shared_module_manager.h | 3 + ecmascript/module/module_resolver.cpp | 118 +++++++++++++++--- ecmascript/module/module_resolver.h | 45 +++++++ ecmascript/module/tests/ecma_module_test.cpp | 28 ++++- 21 files changed, 359 insertions(+), 85 deletions(-) diff --git a/ecmascript/dfx/hprof/tests/hprof_test.cpp b/ecmascript/dfx/hprof/tests/hprof_test.cpp index e9887b6614..76f2fe59ed 100644 --- a/ecmascript/dfx/hprof/tests/hprof_test.cpp +++ b/ecmascript/dfx/hprof/tests/hprof_test.cpp @@ -197,6 +197,8 @@ public: std::string line; bool hit = false; std::vector nodeNativeSizes; + // first ModuleManager's native size is 0 + nodeNativeSizes.push_back("0"); std::ifstream inputStream(filePath); while (getline(inputStream, line)) { if (!hit && line.find(nodesLable) == line.npos) { @@ -221,7 +223,7 @@ public: } } const Heap* heap = instance->GetHeap(); - if (heap->nativePointerList_.size() != nodeNativeSizes.size() || nodeNativeSizes.size() != nNum) { + if (heap->nativePointerList_.size() != nodeNativeSizes.size() || nodeNativeSizes.size() != nNum + 1) { return false; } int ind = 0; diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 720da8a1ea..4905ce8282 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -463,7 +463,6 @@ EcmaVM::~EcmaVM() DFXJSNApi::StopTracing(this); } #endif - moduleManagers_.DestroyAllNativeObj(); if (!isBundlePack_) { std::shared_ptr jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(assetPath_); @@ -2151,42 +2150,40 @@ void EcmaVM::AddToKeptObjects(JSThread *thread, JSHandle value) globalEnv->SetWeakRefKeepObjects(thread, linkedSet); } -void EcmaVM::AddModuleManager(ModuleManager *moduleManager) +std::atomic *EcmaVM::AddModuleManager(ModuleManager *moduleManager) { - moduleManagers_.PushBack(moduleManager); + return moduleManagers_.Init(moduleManager); } void EcmaVM::ModuleManagers::Iterate(RootVisitor &v) { LockHolder lock(CMCGCMutex_); - for (ModuleManager *moduleManager : moduleManagersVec_) { - moduleManager->Iterate(v); + for (auto &[moduleManager, state] : moduleManagersDeque_) { + // iterate manager which is not ready to release + if (state.load() >= static_cast(ModuleManager::Status::INITIALIZED)) { + moduleManager->Iterate(v); + } } } -template -void EcmaVM::ModuleManagers::PushBack(T v) +std::atomic *EcmaVM::ModuleManagers::Init(ModuleManager *moduleManager) { LockHolder lock(CMCGCMutex_); - moduleManagersVec_.push_back(v); -} - -void EcmaVM::ModuleManagers::DestroyAllNativeObj() -{ - LockHolder lock(CMCGCMutex_); - for (auto &moduleManager : moduleManagersVec_) { - moduleManager->NativeObjDestory(); - } + moduleManagersDeque_.emplace_back(moduleManager, static_cast(ModuleManager::Status::INITIALIZED)); + auto &iter = moduleManagersDeque_.back(); + moduleManager->SetModuleManagerState(&(iter.second)); + return &(iter.second); } void EcmaVM::ModuleManagers::Clear() { LockHolder lock(CMCGCMutex_); - for (auto &moduleManager : moduleManagersVec_) { - delete moduleManager; - moduleManager = nullptr; + for (auto &[moduleManager, state] : moduleManagersDeque_) { + if (state.load() != static_cast(ModuleManager::Status::RELEASED)) { + moduleManager->TryFreeModuleManager(); + } } - moduleManagersVec_.clear(); + moduleManagersDeque_.clear(); } void EcmaVM::InitDataViewTypeTable(const GlobalEnvConstants *constant) diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 856435ae0c..d647325641 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -1316,7 +1316,7 @@ public: static void ClearKeptObjects(JSThread *thread); static void AddToKeptObjects(JSThread *thread, JSHandle value); - void AddModuleManager(ModuleManager *moduleManager); + std::atomic *AddModuleManager(ModuleManager *moduleManager); int8_t GetDataViewType(JSTaggedType type) const { auto result = dataViewTypeTable_.find(type); @@ -1603,15 +1603,12 @@ private: // store multi-context module manager class ModuleManagers { Mutex CMCGCMutex_; - std::vector moduleManagersVec_ {}; + std::deque>> moduleManagersDeque_ {}; public: void Iterate(RootVisitor &v); - template - void PushBack(T moduleManager); - - void DestroyAllNativeObj(); + std::atomic *Init(ModuleManager *moduleManager); void Clear(); } moduleManagers_; diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index 8b3327e1f8..ed356f83f5 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -1507,6 +1507,7 @@ JSHClass *JSThread::GetArrayInstanceHClass(JSHandle env, ElementsKind ModuleManager *JSThread::GetModuleManager() const { + CHECK_NO_GALOBALENV_MODULE_MANAGER; JSHandle globalEnv = GetGlobalEnv(); JSHandle nativePointer(globalEnv->GetModuleManagerNativePointer()); ModuleManager *moduleManager = reinterpret_cast(nativePointer->GetExternalPointer()); diff --git a/ecmascript/jspandafile/js_pandafile_manager.cpp b/ecmascript/jspandafile/js_pandafile_manager.cpp index 4801d0651c..db86fb9ed2 100644 --- a/ecmascript/jspandafile/js_pandafile_manager.cpp +++ b/ecmascript/jspandafile/js_pandafile_manager.cpp @@ -52,6 +52,21 @@ JSPandaFileManager::~JSPandaFileManager() template std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, const CString &filename, std::string_view entryPoint, bool needUpdate, const ExecuteTypes &executeType) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return LoadJSPandaFile(thread, moduleManager, filename, entryPoint, needUpdate, executeType); +} +template std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, + const CString &filename, std::string_view entryPoint, bool needUpdate, const ExecuteTypes &executeType); +template std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, + const CString &filename, std::string_view entryPoint, bool needUpdate, const ExecuteTypes &executeType); + +/* + * moduleManager :current context's moduleManager +*/ +template +std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, ModuleManager *moduleManager, + const CString &filename, std::string_view entryPoint, bool needUpdate, const ExecuteTypes &executeType) { { LockHolder lock(jsPandaFileLock_); @@ -75,7 +90,6 @@ std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *threa } EcmaVM *vm = thread->GetEcmaVM(); - ModuleManager *moduleManager = thread->GetModuleManager(); std::unique_ptr pf; if (!vm->IsBundlePack() && moduleManager->GetExecuteMode() == ModuleExecuteMode::ExecuteBufferMode && !vm->IsRestrictedWorkerThread()) { @@ -134,10 +148,6 @@ std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *threa #endif return jsPandaFile; } -template std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, - const CString &filename, std::string_view entryPoint, bool needUpdate, const ExecuteTypes &executeType); -template std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, - const CString &filename, std::string_view entryPoint, bool needUpdate, const ExecuteTypes &executeType); // The security interface needs to be modified accordingly. std::shared_ptr JSPandaFileManager::LoadJSPandaFile(JSThread *thread, const CString &filename, diff --git a/ecmascript/jspandafile/js_pandafile_manager.h b/ecmascript/jspandafile/js_pandafile_manager.h index 43e9b883af..96512703ab 100644 --- a/ecmascript/jspandafile/js_pandafile_manager.h +++ b/ecmascript/jspandafile/js_pandafile_manager.h @@ -38,6 +38,12 @@ public: bool needUpdate = false, const ExecuteTypes &executeType = ExecuteTypes::STATIC); + template + std::shared_ptr LoadJSPandaFile(JSThread *thread, ModuleManager *moduleManager, + const CString &filename, std::string_view entryPoint, + bool needUpdate = false, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); + std::shared_ptr LoadJSPandaFile(JSThread *thread, const CString &filename, std::string_view entryPoint, const void *buffer, size_t size, bool needUpdate = false); diff --git a/ecmascript/mem/assert_scope.cpp b/ecmascript/mem/assert_scope.cpp index 6913f19174..67f1ebd381 100644 --- a/ecmascript/mem/assert_scope.cpp +++ b/ecmascript/mem/assert_scope.cpp @@ -17,16 +17,18 @@ namespace panda::ecmascript { -using AssertGarbageCollectBit = panda::BitField; // default enable -using AssertHeapAllocBit = AssertGarbageCollectBit::NextFlag; // default enable -using AssertHandleAllocBit = AssertHeapAllocBit::NextFlag; // default enable -using AssertDeRefHandleBit = AssertHandleAllocBit::NextFlag; // default enable -using AssertLocalToShareWeakRefBit = AssertDeRefHandleBit::NextFlag; // default disable +using AssertGarbageCollectBit = panda::BitField; // default enable +using AssertHeapAllocBit = AssertGarbageCollectBit::NextFlag; // default enable +using AssertHandleAllocBit = AssertHeapAllocBit::NextFlag; // default enable +using AssertDeRefHandleBit = AssertHandleAllocBit::NextFlag; // default enable +using AssertLocalToShareWeakRefBit = AssertDeRefHandleBit::NextFlag; // default disable +using AssertGlobalEnvModuleManagerBit = AssertLocalToShareWeakRefBit::NextFlag; // default enable constexpr size_t INITIAL_ASSERT_DATA = AssertGarbageCollectBit::Mask() | AssertHeapAllocBit::Mask() | AssertHandleAllocBit::Mask() | - AssertDeRefHandleBit::Mask(); + AssertDeRefHandleBit::Mask() | + AssertGlobalEnvModuleManagerBit::Mask(); thread_local size_t currentAssertData = INITIAL_ASSERT_DATA; @@ -60,6 +62,9 @@ AssertScopeT::AssertScopeT() : oldData_(currentAssertData) case AssertType::LOCAL_TO_SHARE_WEAK_REF_ASSERT: currentAssertData = AssertLocalToShareWeakRefBit::Update(oldData_.value(), isAllow); break; + case AssertType::GLOBALENV_MODULE_MANAGER_ASSERT: + currentAssertData = AssertGlobalEnvModuleManagerBit::Update(oldData_.value(), isAllow); + break; default: break; } @@ -89,6 +94,8 @@ bool AssertScopeT::IsAllowed() return AssertDeRefHandleBit::Decode(currentAssertData); case AssertType::LOCAL_TO_SHARE_WEAK_REF_ASSERT: return AssertLocalToShareWeakRefBit::Decode(currentAssertData); + case AssertType::GLOBALENV_MODULE_MANAGER_ASSERT: + return AssertGlobalEnvModuleManagerBit::Decode(currentAssertData); default: return true; } @@ -104,5 +111,7 @@ template class PUBLIC_API AssertScopeT; template class PUBLIC_API AssertScopeT; template class PUBLIC_API AssertScopeT; +template class PUBLIC_API AssertScopeT; +template class PUBLIC_API AssertScopeT; } // namespace panda::ecmascript \ No newline at end of file diff --git a/ecmascript/mem/assert_scope.h b/ecmascript/mem/assert_scope.h index fd9010b708..6d5a357249 100644 --- a/ecmascript/mem/assert_scope.h +++ b/ecmascript/mem/assert_scope.h @@ -35,6 +35,7 @@ enum class AssertType : uint8_t { HANDLE_ALLOC_ASSERT, DEREF_HANDLE_ASSERT, LOCAL_TO_SHARE_WEAK_REF_ASSERT, + GLOBALENV_MODULE_MANAGER_ASSERT, LAST_ASSERT_TYPE }; @@ -71,6 +72,8 @@ using DisAllowLocalToShareWeakRefHandle = AssertScopeT; using AllowLocalToShareWeakRefHandle = AssertScopeT; +using DisAllowGlobalEnvModuleManager = AssertScopeT; +using AllowGlobalEnvModuleManager = AssertScopeT; #if (!defined NDEBUG) || (defined RUN_TEST) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DISALLOW_GARBAGE_COLLECTION [[maybe_unused]] DisallowGarbageCollection noGc @@ -104,6 +107,10 @@ using AllowLocalToShareWeakRefHandle = AssertScopeT(hint); + + auto data = reinterpret_cast(hint); + JSThread *thread = data->thread; ThreadManagedScope managedScope(thread); [[maybe_unused]] EcmaHandleScope scope(thread); // pointer is module's name, which will be deregistered. - JSTaggedValue moduleVal = - thread->GetModuleManager()->HostGetImportedModule(pointer); + ModuleManager *moduleManager = data->manager; + JSTaggedValue moduleVal = moduleManager->HostGetImportedModule(pointer); if (moduleVal.IsUndefined()) { + ASSERT(moduleManager != nullptr); + moduleManager->TryFreeModuleManager(); + delete data; return; } @@ -47,16 +53,22 @@ void ModuleDeregister::FreeModuleRecord([[maybe_unused]] void *env, void *pointe CString recordNameStr = SourceTextModule::GetModuleName(module.GetTaggedValue()); if (type != LoadingTypes::DYNAMITC_MODULE) { LOG_FULL(INFO) << "free stable module's ModuleNameSpace" << recordNameStr; + ASSERT(moduleManager != nullptr); + moduleManager->TryFreeModuleManager(); + delete data; return; } std::set decreaseModule = {recordNameStr}; - DecreaseRegisterCounts(thread, module, decreaseModule); + DecreaseRegisterCounts(thread, moduleManager, module, decreaseModule); uint16_t counts = module->GetRegisterCounts(); if (counts == 0) { thread->GetEcmaVM()->RemoveFromDeregisterModuleList(recordNameStr); } LOG_FULL(INFO) << "try to remove module " << recordNameStr << ", register counts is " << counts; + ASSERT(moduleManager != nullptr); + moduleManager->TryFreeModuleManager(); + delete data; } void ModuleDeregister::ReviseLoadedModuleCount(JSThread *thread, const CString &moduleName) @@ -79,10 +91,9 @@ void ModuleDeregister::ReviseLoadedModuleCount(JSThread *thread, const CString & } } -void ModuleDeregister::RemoveModule(JSThread *thread, JSHandle module) +void ModuleDeregister::RemoveModule(JSThread *thread, ModuleManager *moduleManager, JSHandle module) { CString recordName = SourceTextModule::GetModuleName(module.GetTaggedValue()); - ModuleManager *moduleManager = thread->GetModuleManager(); if (!thread->GetEcmaVM()->IsWorkerThread() && (module->GetTypes() == ModuleTypes::APP_MODULE || module->GetTypes() == ModuleTypes::OHOS_MODULE)) { if (TryToRemoveSO(thread, module)) { @@ -132,15 +143,16 @@ void ModuleDeregister::IncreaseRegisterCounts(JSThread *thread, JSHandleSetRegisterCounts(registerNum + 1); } -void ModuleDeregister::DecreaseRegisterCounts(JSThread *thread, JSHandle module, - std::set &decreaseModule) +void ModuleDeregister::DecreaseRegisterCounts(JSThread *thread, ModuleManager *moduleManager, + JSHandle module, std::set &decreaseModule) { if (!module->GetRequestedModules(thread).IsUndefined()) { JSHandle requestedModules(thread, module->GetRequestedModules(thread)); size_t requestedModulesLen = requestedModules->GetLength(); for (size_t idx = 0; idx < requestedModulesLen; idx++) { JSHandle requiredModule = - SourceTextModule::GetModuleFromCacheOrResolveNewOne(thread, module, requestedModules, idx); + SourceTextModule::GetModuleFromCacheOrResolveNewOne(thread, moduleManager, module, + requestedModules, idx); RETURN_IF_ABRUPT_COMPLETION(thread); ASSERT(requiredModule.GetTaggedValue().IsSourceTextModule()); const CString moduleRecordName = module->GetEcmaModuleRecordNameString(); @@ -154,7 +166,7 @@ void ModuleDeregister::DecreaseRegisterCounts(JSThread *thread, JSHandleGetLoadingTypes(); if (type == LoadingTypes::DYNAMITC_MODULE) { - DecreaseRegisterCounts(thread, requiredModule, decreaseModule); + DecreaseRegisterCounts(thread, moduleManager, requiredModule, decreaseModule); } } } @@ -170,7 +182,7 @@ void ModuleDeregister::DecreaseRegisterCounts(JSThread *thread, JSHandleSetRegisterCounts(registerNum); } diff --git a/ecmascript/module/js_module_deregister.h b/ecmascript/module/js_module_deregister.h index d9051638d7..31229a90d3 100644 --- a/ecmascript/module/js_module_deregister.h +++ b/ecmascript/module/js_module_deregister.h @@ -44,15 +44,15 @@ public: static void FreeModuleRecord(void *env, void *pointer, void *hint); - static void RemoveModule(JSThread *thread, JSHandle module); + static void RemoveModule(JSThread *thread, ModuleManager *moduleManager, JSHandle module); static void ReviseLoadedModuleCount(JSThread *thread, const CString &moduleName); static void IncreaseRegisterCounts(JSThread *thread, JSHandle module, std::set &increaseModule); - static void DecreaseRegisterCounts(JSThread *thread, JSHandle module, - std::set &decreaseModule); + static void DecreaseRegisterCounts(JSThread *thread, ModuleManager *moduleManager, + JSHandle module, std::set &decreaseModule); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_MODULE_JS_MODULE_DEREGISTER_H diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index 7e3df3b130..44b9e61536 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -383,14 +383,39 @@ JSTaggedValue ModuleManager::CreateModuleManagerNativePointer(JSThread *thread) { EcmaVM *vm = thread->GetEcmaVM(); ModuleManager *moduleManager = new ModuleManager(vm); + std::atomic *state = vm->AddModuleManager(moduleManager); moduleManager->SyncModuleExecuteMode(thread); auto factory = vm->GetFactory(); JSHandle nativePointer = factory->NewJSNativePointer(reinterpret_cast(moduleManager), - nullptr, nullptr, true); - vm->AddModuleManager(moduleManager); + ModuleManager::FreeModuleManager, + nullptr, true); return nativePointer.GetTaggedValue(); } +void ModuleManager::FreeModuleManager([[maybe_unused]] void *env, void *pointer, void *data) +{ + if (pointer == nullptr) { + return; + } + ModuleManager *moduleManager = reinterpret_cast(pointer); + ASSERT(moduleManager != nullptr); + moduleManager->TryFreeModuleManager(); +} + +void ModuleManager::TryFreeModuleManager() +{ + std::atomic *state = GetModuleManagerState(); + ASSERT(state != nullptr); + // state - 1 + state->fetch_sub(1); + // Ready to release + if (state->load() == static_cast(ModuleManager::Status::READY_TO_RELEASE)) { + state->fetch_sub(1); + NativeObjDestory(); + delete this; + } +} + void ModuleManager::SyncModuleExecuteMode(JSThread *thread) { JSHandle globalEnv = thread->GetGlobalEnv(); diff --git a/ecmascript/module/js_module_manager.h b/ecmascript/module/js_module_manager.h index 7e33ec12cb..5124c07692 100644 --- a/ecmascript/module/js_module_manager.h +++ b/ecmascript/module/js_module_manager.h @@ -30,6 +30,14 @@ enum class ModuleExecuteMode { }; class ModuleManager { public: + enum class Status : uint8_t { + RELEASED = 0, + READY_TO_RELEASE = 1, + INITIALIZED = 2 + }; + static_assert(static_cast(Status::RELEASED) + 2 == static_cast(Status::INITIALIZED) && + static_cast(Status::READY_TO_RELEASE) + 1 == static_cast(Status::INITIALIZED), + "Do not change the order of Status."); explicit ModuleManager(EcmaVM *vm); ~ModuleManager() { @@ -121,12 +129,24 @@ public: return vm_->IsBundlePack(); } static JSTaggedValue CreateModuleManagerNativePointer(JSThread *thread); + static void FreeModuleManager(void *env, void *pointer, void *hint); + void TryFreeModuleManager(); void SyncModuleExecuteMode(JSThread *thread); // fast path ldexternalmodulevar for jit static bool CheckModuleValueOutterResolved(JSThread *thread, int32_t index, JSFunction *jsFunc); static JSTaggedValue GetExternalModuleVarFastPathForJIT(JSThread *thread, int32_t index, JSFunction *jsFunc); + inline void SetModuleManagerState(std::atomic *state) + { + state_ = state; + } + + inline std::atomic *GetModuleManagerState() const + { + return state_; + } + // for ut void ClearResolvedModules() { @@ -148,6 +168,7 @@ private: EcmaVM *vm_ {nullptr}; ModuleManagerMap resolvedModules_; std::atomic isExecuteBuffer_ {ModuleExecuteMode::ExecuteZipMode}; + std::atomic *state_ {nullptr}; friend class EcmaVM; friend class PatchLoader; diff --git a/ecmascript/module/js_module_namespace.cpp b/ecmascript/module/js_module_namespace.cpp index 377c8d3e82..1a1b9560f5 100644 --- a/ecmascript/module/js_module_namespace.cpp +++ b/ecmascript/module/js_module_namespace.cpp @@ -389,8 +389,6 @@ bool ModuleNamespace::ValidateKeysAvailable(JSThread *thread, const JSHandle &nameSpace, const NativePointerCallback &callback) { - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle module(thread, nameSpace->GetModule(thread)); CString moduleStr = SourceTextModule::GetModuleName(module.GetTaggedValue()); int srcLength = strlen(moduleStr.c_str()) + 1; @@ -402,8 +400,21 @@ void ModuleNamespace::SetModuleDeregisterProcession(JSThread *thread, const JSHa char *tmpData = reinterpret_cast(moduleNameData); tmpData[srcLength - 1] = '\0'; ASSERT(nameSpace->GetDeregisterProcession(thread).IsUndefined()); - JSHandle registerPointer = factory->NewJSNativePointer( - reinterpret_cast(moduleNameData), callback, reinterpret_cast(thread), false, srcLength); + JSHandle registerPointer = CreateRegisterPointer(thread, moduleNameData, callback, srcLength); nameSpace->SetDeregisterProcession(thread, registerPointer.GetTaggedValue()); } + +JSHandle ModuleNamespace::CreateRegisterPointer(JSThread *thread, void *moduleNameData, + const NativePointerCallback &callback, int srcLength) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + ModuleManager *moduleManager = thread->GetModuleManager(); + std::atomic *state = moduleManager->GetModuleManagerState(); + ASSERT(state != nullptr); + state->fetch_add(1); + FreeModuleData* data = new FreeModuleData{thread, moduleManager}; + JSHandle registerPointer = factory->NewJSNativePointer( + reinterpret_cast(moduleNameData), callback, reinterpret_cast(data), false, srcLength); + return registerPointer; +} } // namespace panda::ecmascript diff --git a/ecmascript/module/js_module_namespace.h b/ecmascript/module/js_module_namespace.h index 00fe8ec287..fd64a10433 100644 --- a/ecmascript/module/js_module_namespace.h +++ b/ecmascript/module/js_module_namespace.h @@ -20,6 +20,10 @@ #include "ecmascript/js_tagged_value.h" namespace panda::ecmascript { +struct FreeModuleData { + JSThread* thread; + ModuleManager* manager; +}; class ModuleNamespace final : public JSObject { public: CAST_CHECK(ModuleNamespace, IsModuleNamespace); @@ -29,6 +33,9 @@ public: static void SetModuleDeregisterProcession(JSThread *thread, const JSHandle &nameSpace, const NativePointerCallback &callback); + static JSHandle CreateRegisterPointer(JSThread *thread, void *moduleNameData, + const NativePointerCallback &callback, int srcLength); + // 9.4.6.11ModuleNamespaceCreate ( module, exports ) static JSHandle ModuleNamespaceCreate(JSThread *thread, const JSHandle &module, const JSHandle &exports); diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 6718e57143..8d0494b0e9 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -2181,6 +2181,14 @@ void SourceTextModule::HandleErrorStack(JSThread *thread, const CVector SourceTextModule::GetModuleFromCacheOrResolveNewOne(JSThread *thread, const JSHandle module, const JSHandle requestedModules, uint32_t idx) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return GetModuleFromCacheOrResolveNewOne(thread, moduleManager, module, requestedModules, idx); +} + +JSHandle SourceTextModule::GetModuleFromCacheOrResolveNewOne(JSThread *thread, + ModuleManager *moduleManager, const JSHandle module, + const JSHandle requestedModules, uint32_t idx) { JSHandle request(thread, requestedModules->Get(thread, idx)); JSHandle requireModule; @@ -2190,7 +2198,6 @@ JSHandle SourceTextModule::GetModuleFromCacheOrResolveNewOne(J return JSHandle::Cast(request); } // current is shared module: resolve or find request module by request string. - ModuleManager *moduleManager = thread->GetModuleManager(); CString requestStr = ModulePathHelper::Utf8ConvertToString(thread, request.GetTaggedValue()); // may return undefined requireModule = moduleManager->GetImportedModule(requestStr); @@ -2211,7 +2218,8 @@ JSHandle SourceTextModule::GetModuleFromCacheOrResolveNewOne(J */ JSHandle moduleRequests(thread, module->GetModuleRequests(thread)); JSHandle required(thread, moduleRequests->Get(thread, idx)); - JSHandle requiredModule = ModuleResolver::HostResolveImportedModule(thread, module, required); + JSHandle requiredModule = + ModuleResolver::HostResolveImportedModule(thread, moduleManager, module, required); RETURN_HANDLE_IF_ABRUPT_COMPLETION(SourceTextModule, thread); SetRequestedModules(thread, requestedModules, idx, requiredModule, SourceTextModule::IsSharedModule(module)); return JSHandle::Cast(requiredModule); diff --git a/ecmascript/module/js_module_source_text.h b/ecmascript/module/js_module_source_text.h index e0b8fda5b0..3afcbac793 100644 --- a/ecmascript/module/js_module_source_text.h +++ b/ecmascript/module/js_module_source_text.h @@ -426,6 +426,8 @@ public: static void RecordEvaluatedOrError(JSThread *thread, JSHandle module); static JSHandle GetModuleFromCacheOrResolveNewOne(JSThread *thread, const JSHandle module, const JSHandle requestedModules, uint32_t idx); + static JSHandle GetModuleFromCacheOrResolveNewOne(JSThread *thread, ModuleManager *moduleManager, + const JSHandle module, const JSHandle requestedModules, uint32_t idx); static bool PreModuleInstantiation(JSThread *thread, JSHandle module, const ExecuteTypes &executeType); diff --git a/ecmascript/module/js_shared_module_manager.cpp b/ecmascript/module/js_shared_module_manager.cpp index 35aa018739..0853fed2bf 100644 --- a/ecmascript/module/js_shared_module_manager.cpp +++ b/ecmascript/module/js_shared_module_manager.cpp @@ -76,9 +76,16 @@ bool SharedModuleManager::TryInsertInSModuleManager(JSThread *thread, const CStr void SharedModuleManager::AddToResolvedModulesAndCreateSharedModuleMutex( JSThread *thread, const CString &recordName, JSTaggedValue module) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + AddToResolvedModulesAndCreateSharedModuleMutex(thread, moduleManager, recordName, module); +} + +void SharedModuleManager::AddToResolvedModulesAndCreateSharedModuleMutex( + JSThread *thread, ModuleManager *moduleManager, const CString &recordName, JSTaggedValue module) { // Add to normal module resolvedModules_ - thread->GetModuleManager()->AddResolveImportedModule(recordName, module); + moduleManager->AddResolveImportedModule(recordName, module); RuntimeLockHolder locker(thread, mutex_); StateVisit stateVisit; sharedModuleMutex_.emplace(recordName, std::move(stateVisit)); diff --git a/ecmascript/module/js_shared_module_manager.h b/ecmascript/module/js_shared_module_manager.h index 2520d59eac..61520c5d75 100644 --- a/ecmascript/module/js_shared_module_manager.h +++ b/ecmascript/module/js_shared_module_manager.h @@ -63,6 +63,9 @@ public: void AddToResolvedModulesAndCreateSharedModuleMutex(JSThread *thread, const CString &recordName, JSTaggedValue module); + + void AddToResolvedModulesAndCreateSharedModuleMutex(JSThread *thread, ModuleManager *moduleManager, + const CString &recordName, JSTaggedValue module); inline bool AddResolveImportedSModule(const CString &recordName, JSTaggedValue module) { diff --git a/ecmascript/module/module_resolver.cpp b/ecmascript/module/module_resolver.cpp index 639d79d4b1..be3e04e7f7 100644 --- a/ecmascript/module/module_resolver.cpp +++ b/ecmascript/module/module_resolver.cpp @@ -29,10 +29,20 @@ JSHandle ModuleResolver::HostResolveImportedModule(JSThread *thre const JSHandle &module, const JSHandle &moduleRequest, const ExecuteTypes &executeType) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return HostResolveImportedModule(thread, moduleManager, module, moduleRequest, executeType); +} + +JSHandle ModuleResolver::HostResolveImportedModule(JSThread *thread, + ModuleManager *moduleManager, + const JSHandle &module, + const JSHandle &moduleRequest, + const ExecuteTypes &executeType) { return module->GetEcmaModuleRecordNameString().empty() ? - HostResolveImportedModuleBundlePack(thread, module, moduleRequest, executeType) : - HostResolveImportedModuleWithMerge(thread, module, moduleRequest, executeType); + HostResolveImportedModuleBundlePack(thread, moduleManager, module, moduleRequest, executeType) : + HostResolveImportedModuleWithMerge(thread, moduleManager, module, moduleRequest, executeType); } JSHandle ModuleResolver::HostResolveImportedModule(JSThread* thread, @@ -79,6 +89,16 @@ JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThr const JSHandle &module, const JSHandle &moduleRequest, const ExecuteTypes &executeType) +{ + auto moduleManager = thread->GetModuleManager(); + return HostResolveImportedModuleWithMerge(thread, moduleManager, module, moduleRequest, executeType); +} + +JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThread *thread, + ModuleManager *moduleManager, + const JSHandle &module, + const JSHandle &moduleRequest, + const ExecuteTypes &executeType) { CString moduleRequestName = ModulePathHelper::Utf8ConvertToString(thread, moduleRequest.GetTaggedValue()); ReplaceModuleThroughFeature(thread, moduleRequestName); @@ -92,18 +112,17 @@ JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThr baseFilename = module->GetEcmaModuleFilenameString(); } - auto moduleManager = thread->GetModuleManager(); if (SourceTextModule::IsNativeModule(moduleRequestName)) { JSHandle cachedModule = moduleManager->TryGetImportedModule(moduleRequestName); if (!cachedModule->IsUndefined()) { return cachedModule; } - return ResolveNativeModule(thread, moduleRequestName, baseFilename, + return ResolveNativeModule(thread, moduleManager, moduleRequestName, baseFilename, SourceTextModule::GetNativeModuleType(moduleRequestName)); } CString recordName = module->GetEcmaModuleRecordNameString(); - std::shared_ptr pandaFile = - JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, baseFilename, recordName, false, executeType); + std::shared_ptr pandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile( + thread, moduleManager, baseFilename, recordName, false, executeType); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); if (pandaFile == nullptr) { // LCOV_EXCL_BR_LINE LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << baseFilename; @@ -117,7 +136,8 @@ JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThr if (handle != thread->GlobalConstants()->GetHandledNull()) { return handle; } - return HostResolveImportedModuleWithMerge(thread, baseFilename, entryPoint, nullptr, executeType); + return HostResolveImportedModuleWithMerge(thread, moduleManager, baseFilename, + entryPoint, nullptr, executeType); } JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSThread *thread, @@ -126,6 +146,15 @@ JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSTh const ExecuteTypes &executeType) { auto moduleManager = thread->GetModuleManager(); + return HostResolveImportedModuleBundlePack(thread, moduleManager, module, moduleRequest, executeType); +} + +JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSThread *thread, + ModuleManager *moduleManager, + const JSHandle &module, + const JSHandle &moduleRequest, + const ExecuteTypes &executeType) +{ CString moduleRequestStr = ModulePathHelper::Utf8ConvertToString(thread, moduleRequest.GetTaggedValue()); if (moduleManager->IsLocalModuleLoaded(moduleRequestStr)) { return JSHandle(moduleManager->HostGetImportedModule(moduleRequestStr)); @@ -134,8 +163,9 @@ JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSTh CString dirname = base::PathHelper::ResolveDirPath(module->GetEcmaModuleFilenameString()); CString moduleFilename = ResolveFilenameFromNative(thread, dirname, moduleRequestStr); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); - return HostResolveImportedModuleBundlePack(thread, moduleFilename, executeType); + return HostResolveImportedModuleBundlePack(thread, moduleManager, moduleFilename, executeType); } + void ModuleResolver::ReplaceModuleThroughFeature(JSThread *thread, CString &requestName) { const auto vm = thread->GetEcmaVM(); @@ -155,13 +185,25 @@ JSHandle ModuleResolver::ResolveSharedImportedModuleWithMerge(JST const CString &recordName, const JSPandaFile *jsPandaFile, [[maybe_unused]] JSRecordInfo *recordInfo) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return ResolveSharedImportedModuleWithMerge(thread, moduleManager, fileName, + recordName, jsPandaFile, recordInfo); +} + +JSHandle ModuleResolver::ResolveSharedImportedModuleWithMerge(JSThread *thread, + ModuleManager *moduleManager, + const CString &fileName, + const CString &recordName, + const JSPandaFile *jsPandaFile, + [[maybe_unused]] JSRecordInfo *recordInfo) { auto sharedModuleManager = SharedModuleManager::GetInstance(); if (sharedModuleManager->SearchInSModuleManager(thread, recordName)) { return JSHandle(sharedModuleManager->GetSModule(thread, recordName)); } // before resolving module completely, shared-module put into isolate -thread resolvedModules_ temporarily. - JSHandle module = thread->GetModuleManager()->TryGetImportedModule(recordName); + JSHandle module = moduleManager->TryGetImportedModule(recordName); if (!module->IsUndefined()) { return module; } @@ -171,7 +213,7 @@ JSHandle ModuleResolver::ResolveSharedImportedModuleWithMerge(JST SharedModuleHelper::ParseSharedModule(thread, jsPandaFile, recordName, fileName, recordInfo); JSHandle::Cast(moduleRecord)->SetEcmaModuleRecordNameString(recordName); sharedModuleManager->AddToResolvedModulesAndCreateSharedModuleMutex( - thread, recordName, moduleRecord.GetTaggedValue()); + thread, moduleManager, recordName, moduleRecord.GetTaggedValue()); return moduleRecord; } @@ -206,10 +248,22 @@ JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThr const CString &recordName, const JSPandaFile *jsPandaFile, const ExecuteTypes &executeType) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return HostResolveImportedModuleWithMerge(thread, moduleManager, moduleFileName, + recordName, jsPandaFile, executeType); +} + +JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThread *thread, + ModuleManager *moduleManager, + const CString &moduleFileName, + const CString &recordName, + const JSPandaFile *jsPandaFile, + const ExecuteTypes &executeType) { if (jsPandaFile == nullptr) { std::shared_ptr file = JSPandaFileManager::GetInstance()->LoadJSPandaFile( - thread, moduleFileName, recordName, false, executeType); + thread, moduleManager, moduleFileName, recordName, false, executeType); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); if (file == nullptr) { CString msg = "Load file with filename '" + moduleFileName + "' failed, recordName '" + recordName + "'"; @@ -224,9 +278,10 @@ JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThr } if (jsPandaFile->IsSharedModule(recordInfo)) { - return ResolveSharedImportedModuleWithMerge(thread, moduleFileName, recordName, jsPandaFile, recordInfo); + return ResolveSharedImportedModuleWithMerge(thread, moduleManager, moduleFileName, + recordName, jsPandaFile, recordInfo); } - ModuleManager *moduleManager = thread->GetModuleManager(); + JSHandle module = moduleManager->TryGetImportedModule(recordName); if (!module->IsUndefined()) { return module; @@ -237,6 +292,7 @@ JSHandle ModuleResolver::HostResolveImportedModuleWithMerge(JSThr moduleManager->AddResolveImportedModule(recordName, moduleRecord.GetTaggedValue()); return moduleRecord; } + JSHandle ModuleResolver::HostResolveImportedModuleBundlePackBuffer(JSThread *thread, const CString &referencingModule, const JSPandaFile *jsPandaFile, @@ -249,15 +305,24 @@ JSHandle ModuleResolver::HostResolveImportedModuleBundlePackBuffe } return ResolveModuleBundlePack(thread, jsPandaFile, executeType); } + JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSThread *thread, const CString &referencingModule, const ExecuteTypes &executeType) { ModuleManager *moduleManager = thread->GetModuleManager(); + return HostResolveImportedModuleBundlePack(thread, moduleManager, referencingModule, executeType); +} + +JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSThread *thread, + ModuleManager *moduleManager, + const CString &referencingModule, + const ExecuteTypes &executeType) +{ // Can not use jsPandaFile from js_pandafile_executor, need to construct with JSPandaFile::ENTRY_MAIN_FUNCTION std::shared_ptr jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile( - thread, referencingModule, JSPandaFile::ENTRY_MAIN_FUNCTION, false, executeType); + thread, moduleManager, referencingModule, JSPandaFile::ENTRY_MAIN_FUNCTION, false, executeType); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); if (jsPandaFile == nullptr) { // LCOV_EXCL_BR_LINE LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << referencingModule; @@ -278,16 +343,25 @@ JSHandle ModuleResolver::HostResolveImportedModuleBundlePack(JSTh return module; } std::shared_ptr pandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile( - thread, moduleFileName, JSPandaFile::ENTRY_MAIN_FUNCTION, false, executeType); + thread, moduleManager, moduleFileName, JSPandaFile::ENTRY_MAIN_FUNCTION, false, executeType); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); if (pandaFile == nullptr) { // LCOV_EXCL_BR_LINE LOG_FULL(FATAL) << "Load current file's panda file failed. Current file is " << referencingModule; } - return ResolveModuleBundlePack(thread, pandaFile.get(), executeType); + return ResolveModuleBundlePack(thread, moduleManager, pandaFile.get(), executeType); +} + +JSHandle ModuleResolver::ResolveModuleBundlePack(JSThread *thread, + const JSPandaFile *jsPandaFile, + const ExecuteTypes &executeType) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return ResolveModuleBundlePack(thread, moduleManager, jsPandaFile, executeType); } JSHandle ModuleResolver::ResolveModuleBundlePack(JSThread *thread, + ModuleManager *moduleManager, const JSPandaFile *jsPandaFile, const ExecuteTypes &executeType) { @@ -304,7 +378,6 @@ JSHandle ModuleResolver::ResolveModuleBundlePack(JSThread *thread // json file can not be compiled into isolate abc. ASSERT(!jsPandaFile->IsJson(&recordInfo)); ModuleDeregister::InitForDeregisterModule(moduleRecord, executeType); - ModuleManager *moduleManager = thread->GetModuleManager(); moduleManager->AddResolveImportedModule(moduleFileName, moduleRecord.GetTaggedValue()); return moduleRecord; } @@ -313,10 +386,19 @@ JSHandle ModuleResolver::ResolveNativeModule(JSThread *thread, const CString &moduleRequest, const CString &baseFileName, ModuleTypes moduleType) +{ + ModuleManager *moduleManager = thread->GetModuleManager(); + return ResolveNativeModule(thread, moduleManager, moduleRequest, baseFileName, moduleType); +} + +JSHandle ModuleResolver::ResolveNativeModule(JSThread *thread, + ModuleManager *moduleManager, + const CString &moduleRequest, + const CString &baseFileName, + ModuleTypes moduleType) { JSHandle moduleRecord = ModuleDataExtractor::ParseNativeModule(thread, moduleRequest, baseFileName, moduleType); - ModuleManager *moduleManager = thread->GetModuleManager(); moduleManager->AddResolveImportedModule(moduleRequest, moduleRecord.GetTaggedValue()); return moduleRecord; } diff --git a/ecmascript/module/module_resolver.h b/ecmascript/module/module_resolver.h index 0c9c13e1ce..e33ece0885 100644 --- a/ecmascript/module/module_resolver.h +++ b/ecmascript/module/module_resolver.h @@ -27,6 +27,11 @@ public: const JSHandle &module, const JSHandle &moduleRequest, const ExecuteTypes& executeType = ExecuteTypes::STATIC); + static JSHandle HostResolveImportedModule(JSThread *thread, + ModuleManager *moduleManager, + const JSHandle &module, + const JSHandle &moduleRequest, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); static JSHandle PUBLIC_API HostResolveImportedModule(JSThread *thread, const CString &fileName, @@ -51,6 +56,12 @@ public: const CString &baseFileName, ModuleTypes moduleType); + static JSHandle ResolveNativeModule(JSThread *thread, + ModuleManager *moduleManager, + const CString &moduleRequest, + const CString &baseFileName, + ModuleTypes moduleType); + static void ReplaceModuleThroughFeature(JSThread *thread, CString &requestName); private: @@ -59,7 +70,19 @@ private: const JSHandle &moduleRequest, const ExecuteTypes &executeType = ExecuteTypes::STATIC); + static JSHandle HostResolveImportedModuleBundlePack(JSThread *thread, + ModuleManager *moduleManager, + const JSHandle &module, + const JSHandle &moduleRequest, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); + + static JSHandle HostResolveImportedModuleWithMerge(JSThread *thread, + const JSHandle &module, + const JSHandle &moduleRequest, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); + static JSHandle HostResolveImportedModuleWithMerge(JSThread *thread, + ModuleManager *moduleManager, const JSHandle &module, const JSHandle &moduleRequest, const ExecuteTypes &executeType = ExecuteTypes::STATIC); @@ -74,7 +97,19 @@ private: const CString &referencingModule, const ExecuteTypes &executeType = ExecuteTypes::STATIC); + static JSHandle HostResolveImportedModuleBundlePack(JSThread *thread, + ModuleManager *moduleManager, + const CString &referencingModule, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); + + static JSHandle HostResolveImportedModuleWithMerge(JSThread *thread, + const CString &referencingModule, + const CString &recordName, + const JSPandaFile *jsPandaFile = nullptr, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); + static JSHandle HostResolveImportedModuleWithMerge(JSThread *thread, + ModuleManager *moduleManager, const CString &referencingModule, const CString &recordName, const JSPandaFile *jsPandaFile = nullptr, @@ -85,7 +120,17 @@ private: const CString &recordName, const JSPandaFile *jsPandaFile, JSRecordInfo *recordInfo); + static JSHandle ResolveSharedImportedModuleWithMerge(JSThread *thread, + ModuleManager *moduleManager, + const CString &fileName, + const CString &recordName, + const JSPandaFile *jsPandaFile, + JSRecordInfo *recordInfo); + static JSHandle ResolveModuleBundlePack(JSThread *thread, + const JSPandaFile *jsPandaFile, + const ExecuteTypes &executeType = ExecuteTypes::STATIC); static JSHandle ResolveModuleBundlePack(JSThread *thread, + ModuleManager *moduleManager, const JSPandaFile *jsPandaFile, const ExecuteTypes &executeType = ExecuteTypes::STATIC); static JSHandle ResolveModuleWithMerge(JSThread *thread, diff --git a/ecmascript/module/tests/ecma_module_test.cpp b/ecmascript/module/tests/ecma_module_test.cpp index 9eb5264394..a4a3fa58d1 100644 --- a/ecmascript/module/tests/ecma_module_test.cpp +++ b/ecmascript/module/tests/ecma_module_test.cpp @@ -1782,7 +1782,7 @@ HWTEST_F_L0(EcmaModuleTest, DecreaseRegisterCounts2) decreaseModule.insert("module_test_module_test_B"); decreaseModule.insert("b"); module->SetSharedType(SharedTypes::SHARED_MODULE); - ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); + ModuleDeregister::DecreaseRegisterCounts(thread, moduleManager, module, decreaseModule); EXPECT_EQ(module->GetModuleRequests(thread).IsUndefined(), false); } @@ -2853,16 +2853,16 @@ HWTEST_F_L0(EcmaModuleTest, DecreaseRegisterCounts) JSHandle module2 = objectFactory->NewSourceTextModule(); std::set decreaseModule; - ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); + ModuleDeregister::DecreaseRegisterCounts(thread, moduleManager, module, decreaseModule); bool res1 = module->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE; EXPECT_EQ(res1, true); module->SetRegisterCounts(INT8_MAX); - ModuleDeregister::DecreaseRegisterCounts(thread, module, decreaseModule); + ModuleDeregister::DecreaseRegisterCounts(thread, moduleManager, module, decreaseModule); EXPECT_EQ(module->GetModuleRequests(thread).IsUndefined(), false); module2->SetLoadingTypes(LoadingTypes::DYNAMITC_MODULE); - ModuleDeregister::DecreaseRegisterCounts(thread, module2, decreaseModule); + ModuleDeregister::DecreaseRegisterCounts(thread, moduleManager, module2, decreaseModule); bool res2 = module2->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE; EXPECT_EQ(res2, false); } @@ -3849,7 +3849,7 @@ HWTEST_F_L0(EcmaModuleTest, RemoveModule) JSHandle res = moduleManager->TryGetImportedModule("module_test_module_test_C"); EXPECT_NE(res, thread->GlobalConstants()->GetHandledUndefined()); - ModuleDeregister::RemoveModule(thread, module); + ModuleDeregister::RemoveModule(thread, moduleManager, module); res = moduleManager->TryGetImportedModule("module_test_module_test_C"); EXPECT_EQ(res, thread->GlobalConstants()->GetHandledUndefined()); @@ -3869,7 +3869,7 @@ HWTEST_F_L0(EcmaModuleTest, RemoveModule2) JSHandle res = moduleManager->TryGetImportedModule("module_test_module_test_C"); EXPECT_NE(res, thread->GlobalConstants()->GetHandledUndefined()); - ModuleDeregister::RemoveModule(thread, module); + ModuleDeregister::RemoveModule(thread, moduleManager, module); res = moduleManager->TryGetImportedModule("module_test_module_test_C"); EXPECT_EQ(res, thread->GlobalConstants()->GetHandledUndefined()); @@ -4304,4 +4304,20 @@ HWTEST_F_L0(EcmaModuleTest, DeregisterModuleList) EXPECT_EQ(vm->ContainInDeregisterModuleList("@ohos:hilog"), false); EXPECT_EQ(vm->ContainInDeregisterModuleList("com.bundleName.test/moduleName/requestModuleName"), false); } + +HWTEST_F_L0(EcmaModuleTest, TryFreeModuleManagerState) +{ + EcmaVM *vm = thread->GetEcmaVM(); + uint32_t INIT_STATE = 2; + ModuleManager *moduleManager1 = new ModuleManager(vm); + std::atomic *state1 = vm->AddModuleManager(moduleManager1); + state1->fetch_add(1); + moduleManager1->TryFreeModuleManager(); + EXPECT_EQ(state1->load(), INIT_STATE); + + ModuleManager *moduleManager2 = new ModuleManager(vm); + std::atomic *state2 = vm->AddModuleManager(moduleManager2); + moduleManager2->TryFreeModuleManager(); + EXPECT_EQ(state2->load(), 0); +} } // namespace panda::test -- Gitee