• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "ecmascript/jspandafile/js_pandafile_manager.h"
17 
18 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
19 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
20 #include "ecmascript/js_file_path.h"
21 #include "ecmascript/jspandafile/js_pandafile.h"
22 #include "ecmascript/jspandafile/program_object.h"
23 #include "ecmascript/module/module_path_helper.h"
24 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
25 #include "file.h"
26 #include "jsnapi.h"
27 
28 namespace panda::ecmascript {
29 using PGOProfilerManager = pgo::PGOProfilerManager;
30 static const size_t MALLOC_SIZE_LIMIT = 2147483648; // Max internal memory used by the VM declared in options
31 
GetInstance()32 JSPandaFileManager *JSPandaFileManager::GetInstance()
33 {
34     static JSPandaFileManager *jsFileManager = new JSPandaFileManager();
35     return jsFileManager;
36 }
37 
~JSPandaFileManager()38 JSPandaFileManager::~JSPandaFileManager()
39 {
40     LockHolder lock(jsPandaFileLock_);
41     extractors_.clear();
42     oldJSPandaFiles_.clear();
43     loadedJSPandaFiles_.clear();
44 }
45 
LoadJSPandaFile(JSThread * thread,const CString & filename,std::string_view entryPoint,bool needUpdate)46 std::shared_ptr<JSPandaFile> JSPandaFileManager::LoadJSPandaFile(JSThread *thread, const CString &filename,
47     std::string_view entryPoint, bool needUpdate)
48 {
49     {
50         LockHolder lock(jsPandaFileLock_);
51         std::shared_ptr<JSPandaFile> jsPandaFile;
52         if (needUpdate) {
53             auto pf = panda_file::OpenPandaFileOrZip(filename, panda_file::File::READ_WRITE);
54             if (pf == nullptr) {
55                 LOG_ECMA(ERROR) << "open file " << filename << " error";
56                 return nullptr;
57             }
58             jsPandaFile = FindJSPandaFileWithChecksum(filename, pf->GetHeader()->checksum);
59         } else {
60             jsPandaFile = FindJSPandaFileUnlocked(filename);
61         }
62         if (jsPandaFile != nullptr) {
63             InsertJSPandaFileVmUnlocked(thread->GetEcmaVM(), jsPandaFile);
64             return jsPandaFile;
65         }
66     }
67 
68     EcmaVM *vm = thread->GetEcmaVM();
69     ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
70     std::unique_ptr<const panda_file::File> pf;
71     if (!vm->IsBundlePack() && moduleManager->GetExecuteMode()) {
72         ResolveBufferCallback resolveBufferCallback = vm->GetResolveBufferCallback();
73         if (resolveBufferCallback == nullptr) {
74             LOG_ECMA(ERROR) << "resolveBufferCallback is nullptr";
75 #if defined(PANDA_TARGET_WINDOWS) || defined(PANDA_TARGET_MACOS)
76             if (vm->EnableReportModuleResolvingFailure()) {
77                 LOG_NO_TAG(ERROR) << "[ArkRuntime Log] Importing shared package is not supported in the Previewer.";
78             }
79 #endif
80             return nullptr;
81         }
82         uint8_t *data = nullptr;
83         size_t dataSize = 0;
84         bool getBuffer = resolveBufferCallback(ModulePathHelper::ParseHapPath(filename), &data, &dataSize);
85         if (!getBuffer) {
86 #if defined(PANDA_TARGET_WINDOWS) || defined(PANDA_TARGET_MACOS)
87             if (vm->EnableReportModuleResolvingFailure()) {
88                 LOG_NO_TAG(INFO) << "[ArkRuntime Log] Importing shared package in the Previewer.";
89             }
90 #endif
91             LOG_ECMA(ERROR) << "resolveBufferCallback get buffer failed";
92             return nullptr;
93         }
94         if (!JSNApi::CheckSecureMem(reinterpret_cast<uintptr_t>(data))) {
95             LOG_ECMA(ERROR) << "Hsp secure memory check failed, please execute in secure memory.";
96             return nullptr;
97         }
98 #if defined(PANDA_TARGET_ANDROID) || defined(PANDA_TARGET_IOS)
99         pf = panda_file::OpenPandaFileFromMemory(data, dataSize);
100 #else
101         pf = panda_file::OpenPandaFileFromSecureMemory(data, dataSize);
102 #endif
103     } else {
104         pf = panda_file::OpenPandaFileOrZip(filename, panda_file::File::READ_WRITE);
105     }
106 
107     if (pf == nullptr) {
108         LOG_ECMA(ERROR) << "open file " << filename << " error";
109         return nullptr;
110     }
111 
112     std::shared_ptr<JSPandaFile> jsPandaFile = GenerateJSPandaFile(thread, pf.release(), filename, entryPoint);
113 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
114     if (thread->GetIsProfiling()) {
115         GetJSPtExtractorAndExtract(jsPandaFile.get());
116     }
117 #endif
118     return jsPandaFile;
119 }
120 
121 // The security interface needs to be modified accordingly.
LoadJSPandaFile(JSThread * thread,const CString & filename,std::string_view entryPoint,const void * buffer,size_t size,bool needUpdate)122 std::shared_ptr<JSPandaFile> JSPandaFileManager::LoadJSPandaFile(JSThread *thread, const CString &filename,
123     std::string_view entryPoint, const void *buffer, size_t size, bool needUpdate)
124 {
125     if (buffer == nullptr || size == 0) {
126         LOG_FULL(ERROR) << "Input buffer is empty";
127         return nullptr;
128     }
129     {
130         LockHolder lock(jsPandaFileLock_);
131         std::shared_ptr<JSPandaFile> jsPandaFile;
132         if (needUpdate) {
133             auto pf = panda_file::OpenPandaFileFromMemory(buffer, size);
134             if (pf == nullptr) {
135                 LOG_ECMA(ERROR) << "open file buffer " << filename << " error";
136                 return nullptr;
137             }
138             jsPandaFile = FindJSPandaFileWithChecksum(filename, pf->GetHeader()->checksum);
139         } else {
140             jsPandaFile = FindJSPandaFileUnlocked(filename);
141         }
142         if (jsPandaFile != nullptr) {
143             InsertJSPandaFileVmUnlocked(thread->GetEcmaVM(), jsPandaFile);
144             return jsPandaFile;
145         }
146     }
147 
148     auto pf = panda_file::OpenPandaFileFromMemory(buffer, size);
149     if (pf == nullptr) {
150         LOG_ECMA(ERROR) << "open file " << filename << " error";
151         return nullptr;
152     }
153 
154     // JSPandaFile desc cannot be empty, if buffer with empty filename, use pf filename as a descriptor.
155     const CString &desc = filename.empty() ? pf->GetFilename().c_str() : filename;
156 
157     std::shared_ptr<JSPandaFile> jsPandaFile = GenerateJSPandaFile(thread, pf.release(), desc, entryPoint);
158 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
159     if (thread->GetIsProfiling()) {
160         GetJSPtExtractorAndExtract(jsPandaFile.get());
161     }
162 #endif
163     return jsPandaFile;
164 }
165 
LoadJSPandaFileSecure(JSThread * thread,const CString & filename,std::string_view entryPoint,uint8_t * buffer,size_t size,bool needUpdate)166 std::shared_ptr<JSPandaFile> JSPandaFileManager::LoadJSPandaFileSecure(JSThread *thread, const CString &filename,
167     std::string_view entryPoint, uint8_t *buffer, size_t size, bool needUpdate)
168 {
169     if (buffer == nullptr || size == 0) {
170         LOG_FULL(ERROR) << "Input buffer is empty";
171         return nullptr;
172     }
173     {
174         LockHolder lock(jsPandaFileLock_);
175         std::shared_ptr<JSPandaFile> jsPandaFile;
176         if (needUpdate) {
177             auto pf = panda_file::OpenPandaFileFromSecureMemory(buffer, size);
178             if (pf == nullptr) {
179                 LOG_ECMA(ERROR) << "open file buffer " << filename << " error";
180                 return nullptr;
181             }
182             jsPandaFile = FindJSPandaFileWithChecksum(filename, pf->GetHeader()->checksum);
183         } else {
184             jsPandaFile = FindJSPandaFileUnlocked(filename);
185         }
186         if (jsPandaFile != nullptr) {
187             InsertJSPandaFileVmUnlocked(thread->GetEcmaVM(), jsPandaFile);
188             return jsPandaFile;
189         }
190     }
191 
192     auto pf = panda_file::OpenPandaFileFromSecureMemory(buffer, size);
193     if (pf == nullptr) {
194         LOG_ECMA(ERROR) << "open file " << filename << " error";
195         return nullptr;
196     }
197 
198     // JSPandaFile desc cannot be empty, if buffer with empty filename, use pf filename as a descriptor.
199     const CString &desc = filename.empty() ? pf->GetFilename().c_str() : filename;
200 
201     std::shared_ptr<JSPandaFile> jsPandaFile = GenerateJSPandaFile(thread, pf.release(), desc, entryPoint);
202 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
203     if (thread->GetIsProfiling()) {
204         GetJSPtExtractorAndExtract(jsPandaFile.get());
205     }
206 #endif
207     return jsPandaFile;
208 }
209 
GenerateProgram(EcmaVM * vm,const JSPandaFile * jsPandaFile,std::string_view entryPoint)210 JSHandle<Program> JSPandaFileManager::GenerateProgram(EcmaVM *vm, const JSPandaFile *jsPandaFile,
211                                                       std::string_view entryPoint)
212 {
213     ASSERT(GetJSPandaFile(jsPandaFile->GetPandaFile()) != nullptr);
214     return PandaFileTranslator::GenerateProgram(vm, jsPandaFile, entryPoint);
215 }
216 
FindJSPandaFileWithChecksum(const CString & filename,uint32_t checksum)217 std::shared_ptr<JSPandaFile> JSPandaFileManager::FindJSPandaFileWithChecksum(const CString &filename, uint32_t checksum)
218 {
219     std::shared_ptr<JSPandaFile> jsPandaFile = FindJSPandaFileUnlocked(filename);
220     if (jsPandaFile == nullptr) {
221         return nullptr;
222     }
223 
224     if (checksum == jsPandaFile->GetChecksum()) {
225         return jsPandaFile;
226     }
227 
228     LOG_FULL(INFO) << "reload " << filename << " with new checksum";
229     ObsoleteLoadedJSPandaFile(filename);
230     return nullptr;
231 }
232 
FindMergedJSPandaFile()233 std::shared_ptr<JSPandaFile> JSPandaFileManager::FindMergedJSPandaFile()
234 {
235     LockHolder lock(jsPandaFileLock_);
236     for (const auto &iter : loadedJSPandaFiles_) {
237         const std::shared_ptr<JSPandaFile> &jsPandafile = iter.second.first;
238         if (jsPandafile->IsFirstMergedAbc()) {
239             return jsPandafile;
240         }
241     }
242     return nullptr;
243 }
244 
FindJSPandaFileUnlocked(const CString & filename)245 std::shared_ptr<JSPandaFile> JSPandaFileManager::FindJSPandaFileUnlocked(const CString &filename)
246 {
247     if (filename.empty()) {
248         return nullptr;
249     }
250     const auto iter = loadedJSPandaFiles_.find(filename);
251     if (iter == loadedJSPandaFiles_.end()) {
252         return nullptr;
253     }
254     return iter->second.first;
255 }
256 
FindJSPandaFileByNormalizedName(const CString & normalizedName)257 std::shared_ptr<JSPandaFile> JSPandaFileManager::FindJSPandaFileByNormalizedName(const CString &normalizedName)
258 {
259     if (normalizedName.empty()) {
260         return nullptr;
261     }
262     std::shared_ptr<JSPandaFile> result;
263     EnumerateJSPandaFiles([&](const std::shared_ptr<JSPandaFile> &file) -> bool {
264         // normalize path inside and outside sandbox
265         if (file->GetNormalizedFileDesc() == normalizedName) {
266             result = file;
267             return false;
268         }
269         return true;
270     });
271     return result;
272 }
273 
FindJSPandaFile(const CString & filename)274 std::shared_ptr<JSPandaFile> JSPandaFileManager::FindJSPandaFile(const CString &filename)
275 {
276     LockHolder lock(jsPandaFileLock_);
277     return FindJSPandaFileUnlocked(filename);
278 }
279 
GetJSPandaFile(const panda_file::File * pf)280 std::shared_ptr<JSPandaFile> JSPandaFileManager::GetJSPandaFile(const panda_file::File *pf)
281 {
282     LockHolder lock(jsPandaFileLock_);
283     for (const auto &iter : loadedJSPandaFiles_) {
284         const std::shared_ptr<JSPandaFile> &jsPandafile = iter.second.first;
285         if (jsPandafile->GetPandaFile() == pf) {
286             return jsPandafile;
287         }
288     }
289     return nullptr;
290 }
291 
ClearNameMap()292 void JSPandaFileManager::ClearNameMap()
293 {
294     LockHolder lock(jsPandaFileLock_);
295     for (const auto &iter : loadedJSPandaFiles_) {
296         iter.second.first->ClearNameMap();
297     }
298 }
299 
AddJSPandaFileVm(const EcmaVM * vm,const std::shared_ptr<JSPandaFile> & jsPandaFile)300 void JSPandaFileManager::AddJSPandaFileVm(const EcmaVM *vm, const std::shared_ptr<JSPandaFile> &jsPandaFile)
301 {
302     const auto &filename = jsPandaFile->GetJSPandaFileDesc();
303     LockHolder lock(jsPandaFileLock_);
304     if (loadedJSPandaFiles_.find(filename) != loadedJSPandaFiles_.end()) {
305         LOG_ECMA(FATAL) << "add failed, file already exist: " << filename;
306         UNREACHABLE();
307     }
308 
309     std::set<const EcmaVM *> vmSet {vm};
310     JSPandaFileVmsPair pandaFileRecord = std::make_pair(jsPandaFile, std::move(vmSet));
311     loadedJSPandaFiles_[filename] = std::move(pandaFileRecord);
312     LOG_ECMA(DEBUG) << "add file: " << filename;
313 }
314 
InsertJSPandaFileVmUnlocked(const EcmaVM * vm,const std::shared_ptr<JSPandaFile> & jsPandaFile)315 void JSPandaFileManager::InsertJSPandaFileVmUnlocked(const EcmaVM *vm,
316                                                      const std::shared_ptr<JSPandaFile> &jsPandaFile)
317 {
318     const auto &filename = jsPandaFile->GetJSPandaFileDesc();
319     auto iter = loadedJSPandaFiles_.find(filename);
320     if (iter == loadedJSPandaFiles_.end()) {
321         LOG_ECMA(FATAL) << "insert vm failed, file not exist: " << filename;
322         UNREACHABLE();
323     }
324 
325     auto &vmSet = iter->second.second;
326     vmSet.emplace(vm);
327 }
328 
RemoveJSPandaFileVm(const EcmaVM * vm,const JSPandaFile * jsPandaFile)329 void JSPandaFileManager::RemoveJSPandaFileVm(const EcmaVM *vm, const JSPandaFile *jsPandaFile)
330 {
331     if (jsPandaFile == nullptr) {
332         return;
333     }
334 
335     LockHolder lock(jsPandaFileLock_);
336     auto iterOld = oldJSPandaFiles_.begin();
337     while (iterOld != oldJSPandaFiles_.end()) {
338         if (iterOld->first.get() == jsPandaFile) {
339             auto &vmSet = iterOld->second;
340             vmSet.erase(vm);
341             if (vmSet.empty()) {
342                 extractors_.erase(jsPandaFile);
343                 oldJSPandaFiles_.erase(iterOld);
344             }
345             return;
346         }
347         iterOld++;
348     }
349     const auto &filename = jsPandaFile->GetJSPandaFileDesc();
350     auto iter = loadedJSPandaFiles_.find(filename);
351     if (iter != loadedJSPandaFiles_.end()) {
352         auto &vmSet = iter->second.second;
353         vmSet.erase(vm);
354         if (vmSet.empty()) {
355             extractors_.erase(jsPandaFile);
356             // erase shared_ptr from map, the ref count -1.
357             loadedJSPandaFiles_.erase(iter);
358         }
359     }
360 }
361 
ObsoleteLoadedJSPandaFile(const CString & filename)362 void JSPandaFileManager::ObsoleteLoadedJSPandaFile(const CString &filename)
363 {
364     auto iter = loadedJSPandaFiles_.find(filename);
365     ASSERT(iter != loadedJSPandaFiles_.end());
366     std::shared_ptr<JSPandaFile> &jsPandaFile = iter->second.first;
367     if (oldJSPandaFiles_.find(jsPandaFile) == oldJSPandaFiles_.end()) {
368         oldJSPandaFiles_.emplace(jsPandaFile, iter->second.second);
369     } else {
370         auto &oldVmSet = oldJSPandaFiles_[jsPandaFile];
371         auto &vmSet = iter->second.second;
372         oldVmSet.insert(vmSet.begin(), vmSet.end());
373     }
374     loadedJSPandaFiles_.erase(iter);
375 }
376 
OpenJSPandaFile(const CString & filename)377 std::shared_ptr<JSPandaFile> JSPandaFileManager::OpenJSPandaFile(const CString &filename)
378 {
379     return OpenJSPandaFile(filename, filename);
380 }
381 
OpenJSPandaFile(const CString & filename,const CString & desc)382 std::shared_ptr<JSPandaFile> JSPandaFileManager::OpenJSPandaFile(const CString &filename, const CString &desc)
383 {
384     auto pf = panda_file::OpenPandaFileOrZip(filename, panda_file::File::READ_WRITE);
385     if (pf == nullptr) {
386         LOG_ECMA(ERROR) << "open file " << filename << " error";
387         return nullptr;
388     }
389 
390     return NewJSPandaFile(pf.release(), desc);
391 }
392 
OpenJSPandaFileFromBuffer(uint8_t * buffer,size_t size,const CString & filename)393 std::shared_ptr<JSPandaFile> JSPandaFileManager::OpenJSPandaFileFromBuffer(uint8_t *buffer,
394                                                                            size_t size,
395                                                                            const CString &filename)
396 {
397     auto pf = panda_file::OpenPandaFileFromMemory(buffer, size);
398     if (pf == nullptr) {
399         LOG_ECMA(ERROR) << "open file " << filename << " error";
400         return nullptr;
401     }
402 
403     return NewJSPandaFile(pf.release(), filename);
404 }
405 
NewJSPandaFile(const panda_file::File * pf,const CString & desc)406 std::shared_ptr<JSPandaFile> JSPandaFileManager::NewJSPandaFile(const panda_file::File *pf, const CString &desc)
407 {
408     std::shared_ptr<JSPandaFile> jsPandaFile = std::make_shared<JSPandaFile>(pf, desc);
409     PGOProfilerManager::GetInstance()->SamplePandaFileInfo(jsPandaFile->GetChecksum(),
410                                                            jsPandaFile->GetJSPandaFileDesc());
411     return jsPandaFile;
412 }
413 
GetJSPtExtractor(const JSPandaFile * jsPandaFile)414 DebugInfoExtractor *JSPandaFileManager::GetJSPtExtractor(const JSPandaFile *jsPandaFile)
415 {
416     LOG_ECMA_IF(jsPandaFile == nullptr, FATAL) << "GetJSPtExtractor error, js pandafile is nullptr";
417 
418     LockHolder lock(jsPandaFileLock_);
419     const auto &filename = jsPandaFile->GetJSPandaFileDesc();
420     if (loadedJSPandaFiles_.find(filename) == loadedJSPandaFiles_.end()) {
421         LOG_ECMA(FATAL) << "get extractor failed, file not exist: " << filename;
422         UNREACHABLE();
423     }
424 
425     auto iter = extractors_.find(jsPandaFile);
426     if (iter == extractors_.end()) {
427         auto extractorPtr = std::make_unique<DebugInfoExtractor>(jsPandaFile);
428         DebugInfoExtractor *extractor = extractorPtr.get();
429         extractors_[jsPandaFile] = std::move(extractorPtr);
430         return extractor;
431     }
432 
433     return iter->second.get();
434 }
435 
GetJSPtExtractorAndExtract(const JSPandaFile * jsPandaFile)436 DebugInfoExtractor *JSPandaFileManager::GetJSPtExtractorAndExtract(const JSPandaFile *jsPandaFile)
437 {
438     LOG_ECMA_IF(jsPandaFile == nullptr, FATAL) << "GetJSPtExtractor error, js pandafile is nullptr";
439 
440     LockHolder lock(jsPandaFileLock_);
441     const auto &filename = jsPandaFile->GetJSPandaFileDesc();
442     if (loadedJSPandaFiles_.find(filename) == loadedJSPandaFiles_.end()) {
443         LOG_ECMA(FATAL) << "get extractor failed, file not exist: " << filename;
444         UNREACHABLE();
445     }
446 
447     auto iter = extractors_.find(jsPandaFile);
448     if (iter == extractors_.end()) {
449         auto extractorPtr = std::make_unique<DebugInfoExtractor>(jsPandaFile);
450         DebugInfoExtractor *extractor = extractorPtr.get();
451         extractor->Extract();
452         extractors_[jsPandaFile] = std::move(extractorPtr);
453         return extractor;
454     }
455 
456     return iter->second.get();
457 }
458 
CpuProfilerGetJSPtExtractor(const JSPandaFile * jsPandaFile)459 DebugInfoExtractor *JSPandaFileManager::CpuProfilerGetJSPtExtractor(const JSPandaFile *jsPandaFile)
460 {
461     LOG_ECMA_IF(jsPandaFile == nullptr, FATAL) << "GetJSPtExtractor error, js pandafile is nullptr";
462 
463     LockHolder lock(jsPandaFileLock_);
464     const auto &filename = jsPandaFile->GetJSPandaFileDesc();
465     if (loadedJSPandaFiles_.find(filename) == loadedJSPandaFiles_.end()) {
466         LOG_ECMA(FATAL) << "get extractor failed, file not exist: " << filename;
467         UNREACHABLE();
468     }
469 
470     DebugInfoExtractor *extractor = nullptr;
471     auto iter = extractors_.find(jsPandaFile);
472     if (iter == extractors_.end()) {
473         auto extractorPtr = std::make_unique<DebugInfoExtractor>(jsPandaFile);
474         extractor = extractorPtr.get();
475         extractors_[jsPandaFile] = std::move(extractorPtr);
476     } else {
477         extractor = iter->second.get();
478     }
479 
480     extractor->Extract();
481     return extractor;
482 }
483 
GetModuleNameFromDesc(const std::string & desc)484 std::string GetModuleNameFromDesc(const std::string &desc)
485 {
486     /*
487     handle desc like:
488     case1: /data/storage/el1/bundle/entry/ets/modules.abc -> entry/ets/modules.abc
489     case2: /data/storage/el1/bundle/entry/ets/widgets.abc -> entry/ets/widgets.abc
490     case3: /data/app/el1/bundle/public/com.xx.xx/entry/ets/modules.abc -> entry/ets/modules.abc
491     case4: /data/app/el1/bundle/public/com.xx.xx/entry/ets/widgets.abc -> entry/ets/widgets.abc
492     */
493     auto lastSlash = desc.rfind("/");
494     if (lastSlash == std::string::npos) {
495         LOG_ECMA(DEBUG) << "GetModuleNameFromDesc can't find fisrt /: " << desc;
496         return "";
497     }
498 
499     auto secondLastSlash = desc.rfind("/", lastSlash - 1);
500     if (secondLastSlash == std::string::npos) {
501         LOG_ECMA(DEBUG) << "GetModuleNameFromDesc can't find second /: " << desc;
502         return "";
503     }
504 
505     auto thirdLastSlash = desc.rfind("/", secondLastSlash - 1);
506     if (thirdLastSlash == std::string::npos) {
507         LOG_ECMA(DEBUG) << "GetModuleNameFromDesc can't find third /: " << desc;
508         return "";
509     }
510     // get moduleName from thirdLastSlash to secondLastSlash
511     return desc.substr(thirdLastSlash + 1, secondLastSlash - thirdLastSlash - 1);
512 }
513 
GenerateJSPandaFile(JSThread * thread,const panda_file::File * pf,const CString & desc,std::string_view entryPoint)514 std::shared_ptr<JSPandaFile> JSPandaFileManager::GenerateJSPandaFile(JSThread *thread, const panda_file::File *pf,
515                                                                      const CString &desc, std::string_view entryPoint)
516 {
517     ASSERT(GetJSPandaFile(pf) == nullptr);
518     std::shared_ptr<JSPandaFile> newJsPandaFile = NewJSPandaFile(pf, desc);
519     EcmaVM *vm = thread->GetEcmaVM();
520 
521     std::string moduleName = GetModuleNameFromDesc(desc.c_str());
522     std::string hapPath;
523     SearchHapPathCallBack callback = vm->GetSearchHapPathCallBack();
524     if (callback) {
525         callback(moduleName, hapPath);
526         LOG_ECMA(DEBUG) << "SearchHapPathCallBack moduleName: " << moduleName
527                         << ", fileName:" << desc << ", hapPath: " << hapPath;
528         newJsPandaFile->SetHapPath(hapPath.c_str());
529     }
530 
531     CString methodName = entryPoint.data();
532     if (newJsPandaFile->IsBundlePack()) {
533         // entryPoint maybe is _GLOBAL::func_main_watch to execute func_main_watch
534         auto pos = entryPoint.find_last_of("::");
535         if (pos != std::string_view::npos) {
536             methodName = entryPoint.substr(pos + 1);
537         } else {
538             // default use func_main_0 as entryPoint
539             methodName = JSPandaFile::ENTRY_FUNCTION_NAME;
540         }
541     }
542     PandaFileTranslator::TranslateClasses(newJsPandaFile.get(), methodName);
543 
544     {
545         // For worker, JSPandaFile may be created by another vm.
546         LockHolder lock(jsPandaFileLock_);
547         std::shared_ptr<JSPandaFile> jsPandaFile = FindJSPandaFileUnlocked(desc);
548         if (jsPandaFile != nullptr) {
549             InsertJSPandaFileVmUnlocked(vm, jsPandaFile);
550             newJsPandaFile.reset();
551             return jsPandaFile;
552         } else {
553             AddJSPandaFileVm(vm, newJsPandaFile);
554             return newJsPandaFile;
555         }
556     }
557 }
558 
AllocateBuffer(size_t size)559 void *JSPandaFileManager::AllocateBuffer(size_t size)
560 {
561     return JSPandaFileAllocator::AllocateBuffer(size);
562 }
563 
AllocateBuffer(size_t size)564 void *JSPandaFileManager::JSPandaFileAllocator::AllocateBuffer(size_t size)
565 {
566     if (size == 0) {
567         LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
568         UNREACHABLE();
569     }
570     if (size >= MALLOC_SIZE_LIMIT) {
571         LOG_ECMA_MEM(FATAL) << "size must be less than the maximum";
572         UNREACHABLE();
573     }
574     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
575     void *ptr = malloc(size);
576     if (ptr == nullptr) {
577         LOG_ECMA_MEM(FATAL) << "malloc failed";
578         UNREACHABLE();
579     }
580 #if ECMASCRIPT_ENABLE_ZAP_MEM
581     if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) {
582         LOG_ECMA_MEM(FATAL) << "memset_s failed";
583         UNREACHABLE();
584     }
585 #endif
586     return ptr;
587 }
588 
FreeBuffer(void * mem)589 void JSPandaFileManager::FreeBuffer(void *mem)
590 {
591     JSPandaFileAllocator::FreeBuffer(mem);
592 }
593 
FreeBuffer(void * mem)594 void JSPandaFileManager::JSPandaFileAllocator::FreeBuffer(void *mem)
595 {
596     if (mem == nullptr) {
597         return;
598     }
599     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
600     free(mem);
601 }
602 }  // namespace panda::ecmascript
603