• 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/base/path_helper.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/jspandafile/js_pandafile.h"
20 #include "ecmascript/jspandafile/js_pandafile_executor.h"
21 #include "ecmascript/jspandafile/js_pandafile_manager.h"
22 #include "ecmascript/linked_hash_table.h"
23 #include "ecmascript/module/js_module_manager.h"
24 #include "ecmascript/module/js_module_source_text.h"
25 #include "ecmascript/module/module_data_extractor.h"
26 #include "ecmascript/platform/file.h"
27 #include "ecmascript/require/js_cjs_module.h"
28 #include "ecmascript/tagged_dictionary.h"
29 
30 namespace panda::ecmascript {
31 using PathHelper = base::PathHelper;
32 
FreeModuleRecord(void * pointer,void * hint)33 void ModuleDeregister::FreeModuleRecord(void *pointer, void *hint)
34 {
35     if (pointer == nullptr) {
36         LOG_FULL(FATAL) << "Lacking deregister module's name.";
37         return;
38     }
39     auto thread = reinterpret_cast<JSThread* >(hint);
40 
41     // pointer is module's name, which will be deregistered.
42     JSTaggedValue moduleVal =
43         thread->GetCurrentEcmaContext()->GetModuleManager()->HostGetImportedModule(pointer);
44     if (moduleVal.IsUndefined()) {
45         return;
46     }
47     JSHandle<SourceTextModule> module(thread, SourceTextModule::Cast(moduleVal.GetTaggedObject()));
48     LoadingTypes type = module->GetLoadingTypes();
49     JSTaggedValue moduleRecordName = SourceTextModule::GetModuleName(module.GetTaggedValue());
50     CString recordNameStr = ConvertToString(moduleRecordName);
51     if (type != LoadingTypes::DYNAMITC_MODULE) {
52         LOG_FULL(INFO) << "free stable module's ModuleNameSpace" << recordNameStr;
53     }
54     NativeAreaAllocator* allocator = thread->GetEcmaVM()->GetNativeAreaAllocator();
55     allocator->FreeBuffer(pointer);
56     if (type == LoadingTypes::DYNAMITC_MODULE) {
57         std::set<CString> decreaseModule = {recordNameStr};
58         DecreaseRegisterCounts(thread, module, decreaseModule);
59         uint16_t counts = module->GetRegisterCounts();
60         if (counts == 0) {
61             thread->GetEcmaVM()->RemoveFromDeregisterModuleList(recordNameStr);
62         }
63         LOG_FULL(INFO) << "try to remove module " << recordNameStr << ", register counts is " << counts;
64     }
65 }
66 
ReviseLoadedModuleCount(JSThread * thread,JSTaggedValue moduleName)67 void ModuleDeregister::ReviseLoadedModuleCount(JSThread *thread, JSTaggedValue moduleName)
68 {
69     EcmaVM *vm = thread->GetEcmaVM();
70     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
71     JSHandle<SourceTextModule> module = moduleManager->HostGetImportedModule(moduleName);
72 
73     LoadingTypes type = module->GetLoadingTypes();
74     // do not change stable module's RegisterCounts.
75     if (type == LoadingTypes::STABLE_MODULE) {
76         return;
77     }
78     CString recordNameStr = ConvertToString(moduleName);
79     if (!vm->ContainInDeregisterModuleList(recordNameStr)) {
80         std::set<CString> increaseModule = {recordNameStr};
81         IncreaseRegisterCounts(thread, module, increaseModule);
82     }
83 }
84 
RemoveModule(JSThread * thread,JSHandle<SourceTextModule> module)85 void ModuleDeregister::RemoveModule(JSThread *thread, JSHandle<SourceTextModule> module)
86 {
87     JSTaggedValue moduleRecordName = SourceTextModule::GetModuleName(module.GetTaggedValue());
88     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
89     if (!thread->GetEcmaVM()->IsWorkerThread() &&
90         (module->GetTypes() == ModuleTypes::APP_MODULE || module->GetTypes() == ModuleTypes::OHOS_MODULE)) {
91         if (TryToRemoveSO(thread, module)) {
92             LOG_FULL(INFO) << "Remove native module " << ConvertToString(moduleRecordName).c_str() << " successfully.";
93         } else {
94             LOG_FULL(INFO) << "Remove native module " << ConvertToString(moduleRecordName).c_str() << " failed.";
95         }
96     }
97     JSHandle<NameDictionary> dict(thread, moduleManager->resolvedModules_.GetTaggedObject());
98     int entry = dict->FindEntry(moduleRecordName);
99     LOG_ECMA_IF(entry == -1, FATAL) << "Can not get module: " << ConvertToString(moduleRecordName) <<
100          ", when try to remove the module";
101 
102     moduleManager->resolvedModules_  = NameDictionary::Remove(thread, dict, entry).GetTaggedValue();
103 }
104 
IncreaseRegisterCounts(JSThread * thread,JSHandle<SourceTextModule> module,std::set<CString> & increaseModule)105 void ModuleDeregister::IncreaseRegisterCounts(JSThread *thread, JSHandle<SourceTextModule> module,
106     std::set<CString> &increaseModule)
107 {
108     if (!module->GetRequestedModules().IsUndefined()) {
109         JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
110         size_t requestedModulesLen = requestedModules->GetLength();
111         JSMutableHandle<JSTaggedValue> required(thread, thread->GlobalConstants()->GetUndefined());
112         for (size_t idx = 0; idx < requestedModulesLen; idx++) {
113             required.Update(requestedModules->Get(idx));
114             JSMutableHandle<SourceTextModule> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
115             JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName();
116             CString moduleName;
117             if (moduleRecordName.IsUndefined()) {
118                 JSHandle<JSTaggedValue> requiredVal =
119                     SourceTextModule::HostResolveImportedModule(thread, module, required);
120                 RETURN_IF_ABRUPT_COMPLETION(thread);
121                 requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
122                 moduleName = ConvertToString(requiredModule->GetEcmaModuleFilename());
123             } else {
124                 ASSERT(moduleRecordName.IsString());
125                 JSHandle<JSTaggedValue> requiredVal =
126                     SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required);
127                 RETURN_IF_ABRUPT_COMPLETION(thread);
128                 requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
129                 moduleName = ConvertToString(requiredModule->GetEcmaModuleRecordName());
130             }
131             if (increaseModule.find(moduleName) != increaseModule.end()) {
132                 LOG_FULL(DEBUG) << "Find module cyclical loading, stop increasing.";
133                 requiredModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
134                 return;
135             }
136             increaseModule.emplace(moduleName);
137             LoadingTypes type = requiredModule->GetLoadingTypes();
138             if (type == LoadingTypes::DYNAMITC_MODULE) {
139                 IncreaseRegisterCounts(thread, requiredModule, increaseModule);
140             }
141         }
142     }
143 
144     if (module->GetLoadingTypes() == LoadingTypes::STABLE_MODULE) {
145         return;
146     }
147     uint16_t registerNum = module->GetRegisterCounts();
148     if (registerNum == UINT16_MAX) {
149         module->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
150         return;
151     }
152     module->SetRegisterCounts(registerNum + 1);
153 }
154 
DecreaseRegisterCounts(JSThread * thread,JSHandle<SourceTextModule> module,std::set<CString> & decreaseModule)155 void ModuleDeregister::DecreaseRegisterCounts(JSThread *thread, JSHandle<SourceTextModule> module,
156     std::set<CString> &decreaseModule)
157 {
158     if (!module->GetRequestedModules().IsUndefined()) {
159         JSHandle<TaggedArray> requestedModules(thread, module->GetRequestedModules());
160         size_t requestedModulesLen = requestedModules->GetLength();
161         JSMutableHandle<JSTaggedValue> required(thread, thread->GlobalConstants()->GetUndefined());
162         for (size_t idx = 0; idx < requestedModulesLen; idx++) {
163             required.Update(requestedModules->Get(idx));
164             JSMutableHandle<SourceTextModule> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
165             JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName();
166             CString moduleName;
167             if (moduleRecordName.IsUndefined()) {
168                 JSHandle<JSTaggedValue> requiredVal =
169                     SourceTextModule::HostResolveImportedModule(thread, module, required);
170                 RETURN_IF_ABRUPT_COMPLETION(thread);
171                 requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
172                 moduleName = ConvertToString(requiredModule->GetEcmaModuleFilename());
173             } else {
174                 ASSERT(moduleRecordName.IsString());
175                 JSHandle<JSTaggedValue> requiredVal =
176                     SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required);
177                 RETURN_IF_ABRUPT_COMPLETION(thread);
178                 requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
179                 moduleName = ConvertToString(requiredModule->GetEcmaModuleRecordName());
180             }
181             if (decreaseModule.find(moduleName) != decreaseModule.end()) {
182                 LOG_FULL(DEBUG) << "Find module cyclical loading, stop increasing.";
183                 requiredModule->SetLoadingTypes(LoadingTypes::STABLE_MODULE);
184                 return;
185             }
186             decreaseModule.emplace(moduleName);
187             LoadingTypes type = requiredModule->GetLoadingTypes();
188             if (type == LoadingTypes::DYNAMITC_MODULE) {
189                 DecreaseRegisterCounts(thread, requiredModule, decreaseModule);
190             }
191         }
192     }
193 
194     if (module->GetLoadingTypes() != LoadingTypes::DYNAMITC_MODULE) {
195         return;
196     }
197     uint16_t num = module->GetRegisterCounts();
198     if (num == 0) {
199         LOG_FULL(FATAL) << "moduleNameSpace can not be uninstalled";
200     }
201 
202     uint16_t registerNum = num - 1;
203     if (registerNum == 0) {
204         LOG_FULL(INFO) << "try to remove module " <<
205             ConvertToString(SourceTextModule::GetModuleName(module.GetTaggedValue())).c_str();
206         RemoveModule(thread, module);
207     }
208     module->SetRegisterCounts(registerNum);
209 }
210 } // namespace panda::ecmascript
211