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