• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "ecmascript/module/js_module_deregister.h"
16 
17 #include "ecmascript/checkpoint/thread_state_transition.h"
18 #include "ecmascript/jspandafile/js_pandafile_executor.h"
19 #include "ecmascript/module/module_path_helper.h"
20 #include "ecmascript/module/module_resolver.h"
21 
22 namespace panda::ecmascript {
23 using PathHelper = base::PathHelper;
24 
FreeModuleRecord(void * env,void * pointer,void * hint)25 void ModuleDeregister::FreeModuleRecord([[maybe_unused]] void *env, void *pointer, void *hint)
26 {
27     if (pointer == nullptr) { // LCOV_EXCL_BR_LINE
28         LOG_FULL(FATAL) << "Lacking deregister module's name.";
29         return;
30     }
31     auto thread = reinterpret_cast<JSThread* >(hint);
32     ThreadManagedScope managedScope(thread);
33     [[maybe_unused]] EcmaHandleScope scope(thread);
34 
35     // pointer is module's name, which will be deregistered.
36     JSTaggedValue moduleVal =
37         thread->GetCurrentEcmaContext()->GetModuleManager()->HostGetImportedModule(pointer);
38     if (moduleVal.IsUndefined()) {
39         return;
40     }
41 
42     NativeAreaAllocator* allocator = thread->GetEcmaVM()->GetNativeAreaAllocator();
43     allocator->FreeBuffer(pointer);
44 
45     JSHandle<SourceTextModule> module(thread, SourceTextModule::Cast(moduleVal.GetTaggedObject()));
46     LoadingTypes type = module->GetLoadingTypes();
47     CString recordNameStr = SourceTextModule::GetModuleName(module.GetTaggedValue());
48     if (type != LoadingTypes::DYNAMITC_MODULE) {
49         LOG_FULL(INFO) << "free stable module's ModuleNameSpace" << recordNameStr;
50         return;
51     }
52 
53     std::set<CString> decreaseModule = {recordNameStr};
54     DecreaseRegisterCounts(thread, module, decreaseModule);
55     uint16_t counts = module->GetRegisterCounts();
56     if (counts == 0) {
57         thread->GetEcmaVM()->RemoveFromDeregisterModuleList(recordNameStr);
58     }
59     LOG_FULL(INFO) << "try to remove module " << recordNameStr << ", register counts is " << counts;
60 }
61 
ReviseLoadedModuleCount(JSThread * thread,const CString & moduleName)62 void ModuleDeregister::ReviseLoadedModuleCount(JSThread *thread, const CString &moduleName)
63 {
64     EcmaVM *vm = thread->GetEcmaVM();
65     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
66     if (!moduleManager->IsLocalModuleLoaded(moduleName)) {
67         return;
68     }
69     JSHandle<SourceTextModule> module = moduleManager->HostGetImportedModule(moduleName);
70 
71     LoadingTypes type = module->GetLoadingTypes();
72     // do not change stable module's RegisterCounts.
73     if (type == LoadingTypes::STABLE_MODULE) {
74         return;
75     }
76     if (!vm->ContainInDeregisterModuleList(moduleName)) {
77         std::set<CString> increaseModule = {moduleName};
78         IncreaseRegisterCounts(thread, module, increaseModule);
79     }
80 }
81 
RemoveModule(JSThread * thread,JSHandle<SourceTextModule> module)82 void ModuleDeregister::RemoveModule(JSThread *thread, JSHandle<SourceTextModule> module)
83 {
84     CString recordName = SourceTextModule::GetModuleName(module.GetTaggedValue());
85     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
86     if (!thread->GetEcmaVM()->IsWorkerThread() &&
87         (module->GetTypes() == ModuleTypes::APP_MODULE || module->GetTypes() == ModuleTypes::OHOS_MODULE)) {
88         if (TryToRemoveSO(thread, module)) {
89             LOG_FULL(INFO) << "Remove native module " << recordName << " successfully.";
90         } else {
91             LOG_FULL(INFO) << "Remove native module " << recordName << " failed.";
92         }
93     }
94     moduleManager->RemoveModuleFromCache(recordName);
95 }
96 
IncreaseRegisterCounts(JSThread * thread,JSHandle<SourceTextModule> module,std::set<CString> & increaseModule)97 void ModuleDeregister::IncreaseRegisterCounts(JSThread *thread, JSHandle<SourceTextModule> module,
98     std::set<CString> &increaseModule)
99 {
100     if (!module->GetRequestedModules().IsUndefined()) {
101         JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
102         size_t requestedModulesLen = requestedModules->GetLength();
103         for (size_t idx = 0; idx < requestedModulesLen; idx++) {
104             JSHandle<SourceTextModule> requiredModule = JSHandle<SourceTextModule>::Cast(
105                 SourceTextModule::GetRequestedModule(thread, module, requestedModules, idx));
106             RETURN_IF_ABRUPT_COMPLETION(thread);
107             const CString moduleRecordName = module->GetEcmaModuleRecordNameString();
108             CString moduleName =
109                 moduleRecordName.empty() ? requiredModule->GetEcmaModuleFilenameString() : moduleRecordName;
110             if (increaseModule.find(moduleName) != increaseModule.end()) {
111                 LOG_FULL(DEBUG) << "Find module cyclical loading, stop increasing.";
112                 requiredModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
113                 return;
114             }
115             increaseModule.emplace(moduleName);
116             LoadingTypes type = requiredModule->GetLoadingTypes();
117             if (type == LoadingTypes::DYNAMITC_MODULE) {
118                 IncreaseRegisterCounts(thread, requiredModule, increaseModule);
119             }
120         }
121     }
122 
123     if (module->GetLoadingTypes() == LoadingTypes::STABLE_MODULE) {
124         return;
125     }
126     uint16_t registerNum = module->GetRegisterCounts();
127     if (registerNum == UINT16_MAX) {
128         module->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
129         return;
130     }
131     module->SetRegisterCounts(registerNum + 1);
132 }
133 
DecreaseRegisterCounts(JSThread * thread,JSHandle<SourceTextModule> module,std::set<CString> & decreaseModule)134 void ModuleDeregister::DecreaseRegisterCounts(JSThread *thread, JSHandle<SourceTextModule> module,
135     std::set<CString> &decreaseModule)
136 {
137     if (!module->GetRequestedModules().IsUndefined()) {
138         JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
139         size_t requestedModulesLen = requestedModules->GetLength();
140         for (size_t idx = 0; idx < requestedModulesLen; idx++) {
141             JSHandle<SourceTextModule> requiredModule = JSHandle<SourceTextModule>::Cast(
142                 SourceTextModule::GetRequestedModule(thread, module, requestedModules, idx));
143             RETURN_IF_ABRUPT_COMPLETION(thread);
144             const CString moduleRecordName = module->GetEcmaModuleRecordNameString();
145             CString moduleName =
146                 moduleRecordName.empty() ? requiredModule->GetEcmaModuleFilenameString() : moduleRecordName;
147             if (decreaseModule.find(moduleName) != decreaseModule.end()) {
148                 LOG_FULL(DEBUG) << "Find module cyclical loading, stop increasing.";
149                 requiredModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
150                 return;
151             }
152             decreaseModule.emplace(moduleName);
153             LoadingTypes type = requiredModule->GetLoadingTypes();
154             if (type == LoadingTypes::DYNAMITC_MODULE) {
155                 DecreaseRegisterCounts(thread, requiredModule, decreaseModule);
156             }
157         }
158     }
159 
160     if (module->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE) {
161         return;
162     }
163     uint16_t num = module->GetRegisterCounts();
164     if (num == 0) { // LCOV_EXCL_BR_LINE
165         LOG_FULL(FATAL) << "moduleNameSpace can not be uninstalled";
166     }
167 
168     uint16_t registerNum = num - 1;
169     if (registerNum == 0) {
170         LOG_FULL(INFO) << "try to remove module " << SourceTextModule::GetModuleName(module.GetTaggedValue());
171         RemoveModule(thread, module);
172     }
173     module->SetRegisterCounts(registerNum);
174 }
175 } // namespace panda::ecmascript
176