1 /*
2 * Copyright (c) 2024 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_shared_module_manager.h"
16
17 #include "ecmascript/jspandafile/js_pandafile_executor.h"
18 #include "ecmascript/module/module_path_helper.h"
19 #include "ecmascript/runtime_lock.h"
20
21 namespace panda::ecmascript {
22 using StringHelper = base::StringHelper;
23 using JSPandaFile = ecmascript::JSPandaFile;
24 using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo;
25
GetInstance()26 SharedModuleManager* SharedModuleManager::GetInstance()
27 {
28 static SharedModuleManager* instance = new SharedModuleManager();
29 return instance;
30 }
31
Iterate(RootVisitor & v)32 void SharedModuleManager::Iterate(RootVisitor &v)
33 {
34 resolvedSharedModules_.ForEach(
35 [&v](auto iter) { iter->second.VisitRoot([&v](ObjectSlot slot) { v.VisitRoot(Root::ROOT_VM, slot); }); });
36 }
37
SearchInSModuleManagerUnsafe(const CString & recordName)38 bool SharedModuleManager::SearchInSModuleManagerUnsafe(const CString &recordName)
39 {
40 auto entry = resolvedSharedModules_.Find(recordName);
41 if (entry) {
42 return true;
43 }
44 return false;
45 }
46
GetSModuleUnsafe(JSThread * thread,const CString & recordName)47 JSHandle<SourceTextModule> SharedModuleManager::GetSModuleUnsafe(JSThread *thread, const CString &recordName)
48 {
49 auto entry = resolvedSharedModules_.Find(recordName);
50 if (!entry) {
51 return JSHandle<SourceTextModule>(thread->GlobalConstants()->GetHandledUndefined());
52 }
53 JSHandle<JSTaggedValue> module(thread, entry.value());
54 return JSHandle<SourceTextModule>::Cast(module);
55 }
56
GetSModule(JSThread * thread,const CString & recordName)57 JSHandle<SourceTextModule> SharedModuleManager::GetSModule(JSThread *thread, const CString &recordName)
58 {
59 RuntimeLockHolder locker(thread, mutex_);
60 return GetSModuleUnsafe(thread, recordName);
61 }
62
SearchInSModuleManager(JSThread * thread,const CString & recordName)63 bool SharedModuleManager::SearchInSModuleManager(JSThread *thread, const CString &recordName)
64 {
65 RuntimeLockHolder locker(thread, mutex_);
66 return SearchInSModuleManagerUnsafe(recordName);
67 }
68
TryInsertInSModuleManager(JSThread * thread,const CString & recordName,const JSHandle<SourceTextModule> & moduleRecord)69 bool SharedModuleManager::TryInsertInSModuleManager(JSThread *thread, const CString &recordName,
70 const JSHandle<SourceTextModule> &moduleRecord)
71 {
72 RuntimeLockHolder locker(thread, mutex_);
73 JSHandle<JSTaggedValue> module = JSHandle<JSTaggedValue>::Cast(moduleRecord);
74 return AddResolveImportedSModule(recordName, module.GetTaggedValue());
75 }
76
AddToResolvedModulesAndCreateSharedModuleMutex(JSThread * thread,const CString & recordName,JSTaggedValue module)77 void SharedModuleManager::AddToResolvedModulesAndCreateSharedModuleMutex(
78 JSThread *thread, const CString &recordName, JSTaggedValue module)
79 {
80 // Add to normal module resolvedModules_
81 thread->GetModuleManager()->AddResolveImportedModule(recordName, module);
82 RuntimeLockHolder locker(thread, mutex_);
83 StateVisit stateVisit;
84 sharedModuleMutex_.emplace(recordName, std::move(stateVisit));
85 }
86
TransferFromLocalToSharedModuleMapAndGetInsertedSModule(JSThread * thread,const JSHandle<SourceTextModule> & module)87 JSHandle<SourceTextModule> SharedModuleManager::TransferFromLocalToSharedModuleMapAndGetInsertedSModule(
88 JSThread *thread, const JSHandle<SourceTextModule> &module)
89 {
90 ASSERT(module->GetSharedType() == SharedTypes::SHARED_MODULE);
91 CString recordName = module->GetEcmaModuleRecordNameString();
92 bool success = TryInsertInSModuleManager(thread, recordName, module);
93 thread->GetModuleManager()->RemoveModuleNameFromList(recordName);
94 return success? module : GetSModule(thread, recordName);
95 }
96
FindModuleMutexWithLock(JSThread * thread,const JSHandle<SourceTextModule> & module)97 StateVisit &SharedModuleManager::FindModuleMutexWithLock(JSThread *thread, const JSHandle<SourceTextModule> &module)
98 {
99 RuntimeLockHolder locker(thread, mutex_);
100 CString moduleName = SourceTextModule::GetModuleName(module.GetTaggedValue());
101 auto it = sharedModuleMutex_.find(moduleName);
102 if (it == sharedModuleMutex_.end()) { // LCOV_EXCL_BR_LINE
103 LOG_ECMA(FATAL) << " Get shared module mutex failed, moduleName is " << moduleName;
104 }
105 return it->second;
106 }
107
IsInstantiatedSModule(JSThread * thread,const JSHandle<SourceTextModule> & module)108 bool SharedModuleManager::IsInstantiatedSModule(JSThread *thread, const JSHandle<SourceTextModule> &module)
109 {
110 RuntimeLockHolder locker(thread, mutex_);
111 return (module->GetStatus() >= ModuleStatus::INSTANTIATED);
112 }
113
GenerateFuncModule(JSThread * thread,const JSPandaFile * jsPandaFile,const CString & entryPoint,ClassKind classKind)114 JSHandle<JSTaggedValue> SharedModuleManager::GenerateFuncModule(JSThread *thread, const JSPandaFile *jsPandaFile,
115 const CString &entryPoint, ClassKind classKind)
116 {
117 CString recordName = jsPandaFile->GetRecordName(entryPoint);
118 auto vm = thread->GetEcmaVM();
119 JSRecordInfo *recordInfo = jsPandaFile->CheckAndGetRecordInfo(recordName);
120 ASSERT(recordInfo != nullptr);
121 if (jsPandaFile->IsModule(recordInfo)) {
122 JSHandle<SourceTextModule> module;
123 if (jsPandaFile->IsSharedModule(recordInfo)) {
124 return JSHandle<JSTaggedValue>(GetSModule(thread, entryPoint));
125 } else {
126 ModuleManager *moduleManager = thread->GetModuleManager();
127 module = moduleManager->HostGetImportedModule(recordName);
128 }
129
130 if (classKind == ClassKind::NON_SENDABLE) {
131 return JSHandle<JSTaggedValue>(module);
132 } else {
133 // Clone isolate module at shared-heap to mark sendable class.
134 return SendableClassModule::GenerateSendableFuncModule(thread, JSHandle<JSTaggedValue>(module));
135 }
136 }
137 return JSHandle<JSTaggedValue>(vm->GetFactory()->NewFromUtf8(recordName));
138 }
139
SModuleNamespaceCreate(JSThread * thread,const JSHandle<JSTaggedValue> & module,const JSHandle<TaggedArray> & exports)140 JSHandle<ModuleNamespace> SharedModuleManager::SModuleNamespaceCreate(JSThread *thread,
141 const JSHandle<JSTaggedValue> &module, const JSHandle<TaggedArray> &exports)
142 {
143 RuntimeLockHolder locker(thread, mutex_);
144 return JSSharedModule::SModuleNamespaceCreate(thread, module, exports);
145 }
146
SharedNativeObjDestory()147 void SharedModuleManager::SharedNativeObjDestory()
148 {
149 resolvedSharedModules_.ForEach([](auto it) {
150 CString key = it->first;
151 ASSERT(!key.empty());
152 GCRoot &root = it->second;
153 JSTaggedValue module = root.Read();
154 SourceTextModule::Cast(module)->DestoryLazyImportArray();
155 SourceTextModule::Cast(module)->DestoryEcmaModuleFilenameString();
156 SourceTextModule::Cast(module)->DestoryEcmaModuleRecordNameString();
157 });
158 }
159 } // namespace panda::ecmascript
160