1/* 2 * Copyright (c) 2021-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/compiler/aot_file/aot_file_manager.h" 16 17#include <utility> 18 19#include "ecmascript/compiler/aot_snapshot/aot_snapshot_constants.h" 20#include "ecmascript/js_file_path.h" 21#include "ecmascript/ohos/framework_helper.h" 22#include "ecmascript/ohos/ohos_preload_app_info.h" 23#include "ecmascript/snapshot/mem/snapshot.h" 24#include "ecmascript/stackmap/ark_stackmap_parser.h" 25 26namespace panda::ecmascript { 27using CommonStubCSigns = kungfu::CommonStubCSigns; 28using BytecodeStubCSigns = kungfu::BytecodeStubCSigns; 29using SnapshotGlobalData = kungfu::SnapshotGlobalData; 30 31#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM) 32JsAotReaderCallback AOTFileManager::jsAotReader_ = nullptr; 33#endif 34 35void AOTLiteralInfo::InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t capacity, uint32_t extraLength) 36{ 37 TaggedArray::InitializeWithSpecialValue(initValue, capacity + RESERVED_LENGTH, extraLength); 38 SetIhc(JSTaggedValue::Undefined()); 39 SetChc(JSTaggedValue::Undefined()); 40 SetLiteralType(JSTaggedValue(INVALID_LITERAL_TYPE)); 41} 42 43void AOTLiteralInfo::SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value) 44{ 45 Set(thread, index, value); 46} 47 48void AOTFileManager::Iterate(const RootVisitor &v) 49{ 50 for (auto &iter : aiDatum_) { 51 auto &aiData = iter.second; 52 for (auto &eachFileData : aiData) { 53 auto &cpMap = eachFileData.second.multiCpsMap_; 54 for (auto &eachCpPair : cpMap) { 55 v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&eachCpPair.second))); 56 } 57 } 58 } 59} 60 61#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM) 62void AOTFileManager::SetJsAotReader(JsAotReaderCallback cb) 63{ 64 jsAotReader_ = cb; 65} 66 67JsAotReaderCallback AOTFileManager::GetJsAotReader() 68{ 69 return jsAotReader_; 70} 71#endif 72 73bool AOTFileManager::AOTFileExist(const std::string &aotFileName, const std::string &extension) 74{ 75 std::string realPath; 76 std::string filename = aotFileName + extension; 77 if (!RealPath(filename, realPath, false)) { 78 return false; 79 } 80 return FileExist(realPath.c_str()); 81} 82 83void AOTFileManager::DumpAOTInfo() 84{ 85 AnFileDataManager *m = AnFileDataManager::GetInstance(); 86 m->Dump(); 87} 88 89void AOTFileManager::LoadStubFile(const std::string &fileName) 90{ 91 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 92 if (!anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::STUB)) { 93 return; 94 } 95 auto info = anFileDataManager->SafeGetStubFileInfo(); 96 auto stubs = info->GetStubs(); 97 InitializeStubEntries(stubs); 98} 99 100bool AOTFileManager::LoadAnFile(const std::string &fileName) 101{ 102 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 103#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM) 104 return anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::AOT, GetJsAotReader()); 105#else 106 return anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::AOT); 107#endif 108} 109 110bool AOTFileManager::LoadAiFile([[maybe_unused]] const std::string &filename) 111{ 112 Snapshot snapshot(vm_); 113#if !WIN_OR_MAC_OR_IOS_PLATFORM 114 #if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM) 115 return snapshot.Deserialize(SnapshotType::AI, filename.c_str(), GetJsAotReader()); 116 #else 117 return snapshot.Deserialize(SnapshotType::AI, filename.c_str()); 118 #endif 119#else 120 return true; 121#endif 122} 123 124bool AOTFileManager::LoadAiFile(const JSPandaFile *jsPandaFile) 125{ 126 uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex(); 127 // this abc file does not have corresponding an file 128 if (anFileInfoIndex == INVALID_INDEX) { 129 return false; 130 } 131 132 auto iter = aiDatum_.find(anFileInfoIndex); 133 // already loaded 134 if (iter != aiDatum_.end()) { 135 return false; 136 } 137 138 std::string aiFilename = ""; 139 // device side aot compile success 140 if (AnFileDataManager::GetInstance()->IsEnable()) { 141 std::string moduleName(vm_->GetModuleName()); 142 std::string aotFileName; 143 JSNApi::LoadAotFileInternal(vm_, moduleName, aotFileName); 144 aiFilename = aotFileName + FILE_EXTENSION_AI; 145 } else { 146 std::string moduleName = JSFilePath::GetHapName(jsPandaFile); 147 std::string hapPath = jsPandaFile->GetJSPandaFileHapPath().c_str(); 148 aiFilename = OhosPreloadAppInfo::GetPreloadAOTFileName(hapPath, moduleName) + FILE_EXTENSION_AI; 149 } 150 151 if (aiFilename.empty()) { 152 LOG_ECMA(INFO) << "current thread can not find ai file"; 153 return false; 154 } 155 156 LoadAiFile(aiFilename); 157 return true; 158} 159 160const std::shared_ptr<AnFileInfo> AOTFileManager::GetAnFileInfo(const JSPandaFile *jsPandaFile) const 161{ 162 uint32_t index = jsPandaFile->GetAOTFileInfoIndex(); 163 if (index == INVALID_INDEX) { 164 return nullptr; 165 } 166 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 167 return anFileDataManager->SafeGetAnFileInfo(index); 168} 169 170uint32_t AOTFileManager::GetFileIndex(uint32_t anFileInfoIndex, CString abcNormalizedName) const 171{ 172 auto fileIndex = INVALID_INDEX; 173 if (abcNormalizedName.find(JSFilePath::GetBaseName(STUB_AN_FILE)) == std::string::npos) { 174 auto aiDatumIter = aiDatum_.find(anFileInfoIndex); 175 if (aiDatumIter == aiDatum_.end()) { 176 return INVALID_INDEX; 177 } 178 179 auto fileIter = aiDatumIter->second.find(abcNormalizedName); 180 if (fileIter == aiDatumIter->second.end()) { 181 return INVALID_INDEX; 182 } 183 fileIndex = fileIter->second.fileIndex_; 184 } else { 185 fileIndex = STUB_FILE_INDEX; 186 } 187 return fileIndex; 188} 189 190bool AOTFileManager::IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry) const 191{ 192 if (!jsPandaFile->IsLoadedAOT()) { 193 return false; 194 } 195 196 const std::shared_ptr<AnFileInfo> anFileInfo = GetAnFileInfo(jsPandaFile); 197 if (anFileInfo == nullptr) { 198 return false; 199 } 200 201 auto fileIndex = GetFileIndex(jsPandaFile->GetAOTFileInfoIndex(), jsPandaFile->GetNormalizedFileDesc().c_str()); 202 if (fileIndex == INVALID_INDEX) { 203 return false; 204 } 205 return anFileInfo->IsLoadMain(fileIndex, jsPandaFile, entry); 206} 207 208std::list<CString> AOTFileManager::GetPandaFiles(uint32_t aotFileInfoIndex) 209{ 210 std::list<CString> abcFilesList {}; 211 auto aiDatumIter = aiDatum_.find(aotFileInfoIndex); 212 if (aiDatumIter == aiDatum_.end()) { 213 return abcFilesList; 214 } 215 for (const auto& nameIter : aiDatumIter->second) { 216 abcFilesList.push_back(nameIter.first); 217 } 218 return abcFilesList; 219} 220 221void AOTFileManager::BindPreloadedPandaFilesInAotFile(const std::string &moduleName) 222{ 223 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 224 uint32_t aotFileInfoIndex = anFileDataManager->SafeGetFileInfoIndex(moduleName + FILE_EXTENSION_AN); 225 if (aotFileInfoIndex == INVALID_INDEX) { 226 return; 227 } 228 auto abcFiles = GetPandaFiles(aotFileInfoIndex); 229 for (const auto &abcNormalizedName : abcFiles) { 230 const auto abcFile = JSPandaFileManager::GetInstance()->FindJSPandaFileByNormalizedName(abcNormalizedName); 231 if (!abcFile) { 232 LOG_ECMA(WARN) << "Can not find file: " << abcNormalizedName << " in module: " << moduleName; 233 continue; 234 } 235 if (!abcFile->IsLoadedAOT()) { 236 abcFile->SetAOTFileInfoIndex(aotFileInfoIndex); 237 LOG_ECMA(INFO) << "Bind file: " << abcNormalizedName << ", aotFileInfoIndex: " << aotFileInfoIndex 238 << " in module: " << moduleName; 239 } 240 } 241} 242 243bool AOTFileManager::HasPandaFile(uint32_t aotFileInfoIndex, const CString &abcNormalizedName) const 244{ 245 auto aiDatumIter = aiDatum_.find(aotFileInfoIndex); 246 if (aiDatumIter == aiDatum_.end()) { 247 return false; 248 } 249 auto pandaCPIter = aiDatumIter->second.find(abcNormalizedName); 250 return pandaCPIter != aiDatumIter->second.end(); 251} 252 253void AOTFileManager::BindPandaFileInAotFile(const std::string &aotFileBaseName, JSPandaFile *jsPandaFile) const 254{ 255 if (jsPandaFile->IsLoadedAOT()) { 256 // already loaded. 257 return; 258 } 259 260 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 261 if (!anFileDataManager->IsEnable()) { 262 return; 263 } 264 uint32_t aotFileInfoIndex = anFileDataManager->SafeGetFileInfoIndex(aotFileBaseName + FILE_EXTENSION_AN); 265 if (aotFileInfoIndex == INVALID_INDEX) { 266 LOG_ECMA(WARN) << "Bind panda file to AOT failed. AOT file not found for " << aotFileBaseName; 267 return; 268 } 269 CString abcNormalizedName(jsPandaFile->GetNormalizedFileDesc()); 270 if (!HasPandaFile(aotFileInfoIndex, abcNormalizedName)) { 271 // not existed in an file. 272 LOG_ECMA(WARN) << "Bind panda file to AOT failed. " << abcNormalizedName << " not found for " 273 << aotFileBaseName; 274 return; 275 } 276 jsPandaFile->SetAOTFileInfoIndex(aotFileInfoIndex); 277 LOG_ECMA(INFO) << "Bind file: " << abcNormalizedName << ", aotFileInfoIndex: " << aotFileInfoIndex 278 << " in aotFileBaseName: " << aotFileBaseName; 279} 280 281uint32_t AOTFileManager::GetAnFileIndex(const JSPandaFile *jsPandaFile) const 282{ 283 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 284 285 // run via command line 286 if (vm_->GetJSOptions().WasAOTOutputFileSet()) { 287 std::string jsPandaFileDesc = jsPandaFile->GetJSPandaFileDesc().c_str(); 288 std::string baseName = JSFilePath::GetFileName(jsPandaFileDesc); 289 if (baseName.empty()) { 290 return INVALID_INDEX; 291 } 292 std::string anFileName = baseName + FILE_EXTENSION_AN; 293 return anFileDataManager->SafeGetFileInfoIndex(anFileName); 294 } 295 296 // run from app hap 297 std::string hapName = JSFilePath::GetHapName(jsPandaFile); 298 if (hapName.empty()) { 299 return INVALID_INDEX; 300 } 301 std::string anFileName = hapName + FILE_EXTENSION_AN; 302 return anFileDataManager->SafeGetFileInfoIndex(anFileName); 303} 304 305bool AOTFileManager::TryReadLock() 306{ 307 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 308 return anFileDataManager->SafeTryReadLock(); 309} 310 311bool AOTFileManager::IsEnableAOT() const 312{ 313 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 314 return anFileDataManager->IsEnable(); 315} 316 317bool AOTFileManager::InsideStub(uintptr_t pc) 318{ 319 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 320 return anFileDataManager->SafeInsideStub(pc); 321} 322 323bool AOTFileManager::InsideAOT(uintptr_t pc) 324{ 325 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 326 return anFileDataManager->SafeInsideAOT(pc); 327} 328 329AOTFileInfo::CallSiteInfo AOTFileManager::CalCallSiteInfo(uintptr_t retAddr, bool isDeopt) 330{ 331 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 332 return anFileDataManager->SafeCalCallSiteInfo(retAddr, isDeopt); 333} 334 335void AOTFileManager::PrintAOTEntry(const JSPandaFile *file, const Method *method, uintptr_t entry) 336{ 337 uint32_t mId = method->GetMethodId().GetOffset(); 338 std::string mName = method->GetMethodName(file); 339 auto &fileName = file->GetJSPandaFileDesc(); 340 LOG_COMPILER(INFO) << "Bind " << mName << "@" << mId << "@" << fileName 341 << " -> AOT-Entry = " << reinterpret_cast<void *>(entry); 342} 343 344void AOTFileManager::SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc, const JSPandaFile *jsPandaFile, 345 std::string_view entryPoint) 346{ 347 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 348 uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex(); 349 const std::shared_ptr<AnFileInfo> anFileInfo = anFileDataManager->SafeGetAnFileInfo(anFileInfoIndex); 350 auto aiDatumIter = aiDatum_.find(anFileInfoIndex); 351 if (aiDatumIter == aiDatum_.end()) { 352 LOG_ECMA(FATAL) << "can not find aiData by anFileInfoIndex " << anFileInfoIndex; 353 UNREACHABLE(); 354 } 355 uint32_t fileIndex = GetFileIndex(jsPandaFile->GetAOTFileInfoIndex(), jsPandaFile->GetNormalizedFileDesc().c_str()); 356 if (fileIndex == INVALID_INDEX) { 357 LOG_ECMA(FATAL) << "can not find aiData by anFileInfoIndex " << anFileInfoIndex 358 << ", normalizedDesc: " << jsPandaFile->GetNormalizedFileDesc(); 359 UNREACHABLE(); 360 } 361 // get main func method 362 auto mainFuncMethodId = jsPandaFile->GetMainMethodIndex(entryPoint.data()); 363 MainFuncEntry mainFuncEntry = anFileInfo->GetMainFuncEntry(fileIndex, mainFuncMethodId); 364 uint64_t mainEntry = mainFuncEntry.mainEntry; 365 int32_t fpDelta = mainFuncEntry.fpDelta; 366 bool isFastCall = mainFuncEntry.isFastCall; 367 MethodLiteral *mainMethod = jsPandaFile->FindMethodLiteral(mainFuncMethodId); 368 if (mainMethod == nullptr) { 369 LOG_ECMA(FATAL) << "empty main method literal"; 370 UNREACHABLE(); 371 } 372 mainMethod->SetAotCodeBit(true); 373 mainMethod->SetNativeBit(false); 374 Method *method = mainFunc->GetCallTarget(); 375 method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold()); 376 method->SetCodeEntryAndMarkAOTWhenBinding(static_cast<uintptr_t>(mainEntry)); 377 method->SetFpDelta(fpDelta); 378 method->SetIsFastCall(isFastCall); 379 mainFunc->SetCompiledFuncEntry(static_cast<uintptr_t>(mainEntry), isFastCall); 380#ifndef NDEBUG 381 PrintAOTEntry(jsPandaFile, method, mainEntry); 382#endif 383 384 MethodLiteral *methodLiteral = method->GetMethodLiteral(); 385 ASSERT(methodLiteral != nullptr); 386 methodLiteral->SetAotCodeBit(true); 387 methodLiteral->SetIsFastCall(isFastCall); 388} 389 390void AOTFileManager::SetAOTFuncEntry(const JSPandaFile *jsPandaFile, JSFunction *function, 391 Method *method, uint32_t entryIndex, bool *canFastCall) 392{ 393 uint64_t methodCodeEntry = method->GetCodeEntryOrLiteral(); 394 if (function != nullptr && methodCodeEntry != reinterpret_cast<uintptr_t>(nullptr)) { 395 function->SetCompiledFuncEntry(methodCodeEntry, method->IsFastCall()); 396 return; 397 } 398 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 399 uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex(); 400 const std::shared_ptr<AnFileInfo> anFileInfo = anFileDataManager->SafeGetAnFileInfo(anFileInfoIndex); 401 const AOTFileInfo::FuncEntryDes &entry = anFileInfo->GetStubDes(entryIndex); 402 uint64_t codeEntry = entry.codeAddr_; 403#ifndef NDEBUG 404 PrintAOTEntry(jsPandaFile, method, codeEntry); 405#endif 406 if (!codeEntry) { 407 return; 408 } 409 method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold()); 410 method->SetCodeEntryAndMarkAOTWhenBinding(codeEntry); 411 method->SetIsFastCall(entry.isFastCall_); 412 method->SetFpDelta(entry.fpDeltaPrevFrameSp_); 413 if (canFastCall != nullptr) { 414 *canFastCall = entry.isFastCall_; 415 } 416 417 MethodLiteral *methodLiteral = method->GetMethodLiteral(); 418 ASSERT(methodLiteral != nullptr); 419 methodLiteral->SetAotCodeBit(true); 420 methodLiteral->SetIsFastCall(entry.isFastCall_); 421} 422 423kungfu::ArkStackMapParser *AOTFileManager::GetStackMapParser() const 424{ 425 return arkStackMapParser_; 426} 427 428void AOTFileManager::AdjustBCStubAndDebuggerStubEntries(JSThread *thread, 429 const std::vector<AOTFileInfo::FuncEntryDes> &stubs, 430 const AsmInterParsedOption &asmInterOpt) 431{ 432 auto defaultBCStubDes = stubs[BytecodeStubCSigns::SingleStepDebugging]; 433 auto defaultBCDebuggerStubDes = stubs[BytecodeStubCSigns::BCDebuggerEntry]; 434 auto defaultBCDebuggerExceptionStubDes = stubs[BytecodeStubCSigns::BCDebuggerExceptionEntry]; 435 ASSERT(defaultBCStubDes.kind_ == kungfu::CallSignature::TargetKind::BYTECODE_HELPER_HANDLER); 436 if (asmInterOpt.handleStart >= 0 && asmInterOpt.handleStart <= asmInterOpt.handleEnd) { 437 for (int i = asmInterOpt.handleStart; i <= asmInterOpt.handleEnd; i++) { 438 thread->SetBCStubEntry(static_cast<size_t>(i), defaultBCStubDes.codeAddr_); 439 } 440#define DISABLE_SINGLE_STEP_DEBUGGING(name) \ 441 thread->SetBCStubEntry(BytecodeStubCSigns::ID_##name, stubs[BytecodeStubCSigns::ID_##name].codeAddr_); 442 INTERPRETER_DISABLE_SINGLE_STEP_DEBUGGING_BC_STUB_LIST(DISABLE_SINGLE_STEP_DEBUGGING) 443#undef DISABLE_SINGLE_STEP_DEBUGGING 444 } 445 for (size_t i = 0; i < BCStubEntries::EXISTING_BC_HANDLER_STUB_ENTRIES_COUNT; i++) { 446 if (i == BytecodeStubCSigns::ID_ExceptionHandler) { 447 thread->SetBCDebugStubEntry(i, defaultBCDebuggerExceptionStubDes.codeAddr_); 448 continue; 449 } 450 thread->SetBCDebugStubEntry(i, defaultBCDebuggerStubDes.codeAddr_); 451 } 452} 453 454void AOTFileManager::InitializeStubEntries(const std::vector<AnFileInfo::FuncEntryDes> &stubs) 455{ 456 auto thread = vm_->GetAssociatedJSThread(); 457 size_t len = stubs.size(); 458 for (size_t i = 0; i < len; i++) { 459 auto des = stubs[i]; 460 if (des.IsCommonStub()) { 461 thread->SetFastStubEntry(des.indexInKindOrMethodId_, des.codeAddr_); 462 } else if (des.IsBCStub()) { 463 thread->SetBCStubEntry(des.indexInKindOrMethodId_, des.codeAddr_); 464#if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG 465 auto start = GET_MESSAGE_STRING_ID(HandleLdundefined); 466 std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start); 467 LOG_ECMA(DEBUG) << "bytecode index: " << des.indexInKindOrMethodId_ << " :" << format << " addr: 0x" 468 << std::hex << des.codeAddr_; 469#endif 470 } else if (des.IsBuiltinsStub()) { 471 thread->SetBuiltinStubEntry(des.indexInKindOrMethodId_, des.codeAddr_); 472#if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG 473 int start = GET_MESSAGE_STRING_ID(StringCharCodeAt); 474 std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start - 1); // -1: NONE 475 LOG_ECMA(DEBUG) << "builtins index: " << std::dec << des.indexInKindOrMethodId_ << " :" << format 476 << " addr: 0x" << std::hex << des.codeAddr_; 477#endif 478 } else if (des.IsBaselineStub()) { 479 thread->SetBaselineStubEntry(des.indexInKindOrMethodId_, des.codeAddr_); 480#if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG 481 int start = GET_MESSAGE_STRING_ID(BaselineTryLdGLobalByNameImm8ID16); 482 std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start - 1); // -1: NONE 483 LOG_ECMA(DEBUG) << "baseline stub index: " << std::dec << des.indexInKindOrMethodId_ << " :" << format 484 << " addr: 0x" << std::hex << des.codeAddr_; 485#endif 486 } else { 487 thread->RegisterRTInterface(des.indexInKindOrMethodId_, des.codeAddr_); 488#if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG 489 int start = GET_MESSAGE_STRING_ID(CallRuntime); 490 std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start); 491 LOG_ECMA(DEBUG) << "runtime index: " << std::dec << des.indexInKindOrMethodId_ << " :" << format 492 << " addr: 0x" << std::hex << des.codeAddr_; 493#endif 494 } 495 } 496 thread->CheckOrSwitchPGOStubs(); 497 AsmInterParsedOption asmInterOpt = vm_->GetJSOptions().GetAsmInterParsedOption(); 498 AdjustBCStubAndDebuggerStubEntries(thread, stubs, asmInterOpt); 499} 500 501bool AOTFileManager::RewriteDataSection(uintptr_t dataSec, size_t size, uintptr_t newData, size_t newSize) 502{ 503 if (memcpy_s(reinterpret_cast<void *>(dataSec), size, reinterpret_cast<void *>(newData), newSize) != EOK) { 504 LOG_FULL(FATAL) << "memset failed"; 505 return false; 506 } 507 return true; 508} 509 510void AOTFileManager::ParseDeserializedData(const CString &snapshotFileName, JSTaggedValue deserializedData) 511{ 512 AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance(); 513 std::string baseName = JSFilePath::GetFileName(snapshotFileName.c_str()); 514 uint32_t anFileInfoIndex = anFileDataManager->SafeGetFileInfoIndex(baseName + FILE_EXTENSION_AN); 515 516 JSThread *thread = vm_->GetJSThread(); 517 FrameworkHelper frameworkHelper(thread); 518 JSHandle<TaggedArray> aiData(thread, deserializedData); 519 uint32_t aiDataLen = aiData->GetLength(); 520 ASSERT(aiDataLen % AOTSnapshotConstants::SNAPSHOT_DATA_ITEM_SIZE == 0); 521 auto aiDatumResult = aiDatum_.try_emplace(anFileInfoIndex); 522 FileNameToMultiConstantPoolMap &fileNameToMulCpMap = aiDatumResult.first->second; 523 524 JSMutableHandle<TaggedArray> fileInfo(thread, JSTaggedValue::Undefined()); 525 JSMutableHandle<TaggedArray> cpList(thread, JSTaggedValue::Undefined()); 526 for (uint32_t i = 0; i < aiDataLen; i += AOTSnapshotConstants::SNAPSHOT_DATA_ITEM_SIZE) { 527 // handle file info 528 fileInfo.Update(aiData->Get(i + SnapshotGlobalData::Cast(SnapshotGlobalData::CP_TOP_ITEM::PANDA_INFO_ID))); 529 auto nameOffset = SnapshotGlobalData::Cast(SnapshotGlobalData::CP_PANDA_INFO_ITEM::NAME_ID); 530 auto indexOffset = SnapshotGlobalData::Cast(SnapshotGlobalData::CP_PANDA_INFO_ITEM::INDEX_ID); 531 CString fileNameCStr = EcmaStringAccessor(fileInfo->Get(nameOffset)).ToCString(); 532 std::string fileNameStr = EcmaStringAccessor(fileInfo->Get(nameOffset)).ToStdString(); 533 uint32_t fileIndex = static_cast<uint32_t>(fileInfo->Get(indexOffset).GetInt()); 534 // handle constant pool 535 cpList.Update(aiData->Get(i + SnapshotGlobalData::Cast(SnapshotGlobalData::CP_TOP_ITEM::CP_ARRAY_ID))); 536 uint32_t cpLen = cpList->GetLength(); 537 ASSERT(cpLen % AOTSnapshotConstants::SNAPSHOT_CP_ARRAY_ITEM_SIZE == 0); 538 auto &PandaCpInfoInserted = fileNameToMulCpMap.try_emplace(fileNameCStr).first->second; 539 PandaCpInfoInserted.fileIndex_ = fileIndex; 540 MultiConstantPoolMap &cpMap = PandaCpInfoInserted.multiCpsMap_; 541 auto context = thread->GetCurrentEcmaContext(); 542 if (cpLen > 0) { 543 JSTaggedValue cp = cpList->Get(AOTSnapshotConstants::SNAPSHOT_CP_ARRAY_ITEM_SIZE - 1); // first constpool 544 context->LoadProtoTransitionTable(cp); 545 } 546 JSMutableHandle<ConstantPool> cpHandle(thread, JSTaggedValue::Undefined()); 547 for (uint32_t pos = 0; pos < cpLen; pos += AOTSnapshotConstants::SNAPSHOT_CP_ARRAY_ITEM_SIZE) { 548 int32_t constantPoolID = cpList->Get(pos).GetInt(); 549 cpHandle.Update(cpList->Get(pos + 1)); 550 context->ResetProtoTransitionTableOnConstpool(cpHandle.GetTaggedValue()); 551 cpMap.insert({constantPoolID, cpHandle.GetTaggedValue()}); 552 // the arkui framework abc file constpool was patched here 553 if (frameworkHelper.IsFrameworkAbcFile(fileNameStr)) { 554 context->UpdateConstpoolWhenDeserialAI(fileNameStr, cpHandle, constantPoolID); 555 } 556 } 557 } 558} 559 560JSHandle<JSTaggedValue> AOTFileManager::GetDeserializedConstantPool(const JSPandaFile *jsPandaFile, int32_t cpID) 561{ 562 // The deserialization of the 'ai' data used by the multi-work 563 // is not implemented yet, so there may be a case where 564 // aiDatum_ is empty, in which case the Hole will be returned 565 if (aiDatum_.empty()) { 566 return JSHandle<JSTaggedValue>(vm_->GetJSThread(), JSTaggedValue::Hole()); 567 } 568 uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex(); 569 auto aiDatumIter = aiDatum_.find(anFileInfoIndex); 570 if (aiDatumIter == aiDatum_.end()) { 571 LOG_COMPILER(FATAL) << "can not find aiData by anFileInfoIndex " << anFileInfoIndex; 572 UNREACHABLE(); 573 } 574 const auto &fileNameToMulCpMap = aiDatumIter->second; 575 auto cpMapIter = fileNameToMulCpMap.find(jsPandaFile->GetNormalizedFileDesc()); 576 if (cpMapIter == fileNameToMulCpMap.end()) { 577 LOG_COMPILER(FATAL) << "can not find constpools by fileName " << jsPandaFile->GetNormalizedFileDesc().c_str(); 578 UNREACHABLE(); 579 } 580 const CMap<int32_t, JSTaggedValue> &cpMap = cpMapIter->second.multiCpsMap_; 581 auto iter = cpMap.find(cpID); 582 if (iter == cpMap.end()) { 583 LOG_COMPILER(FATAL) << "can not find deserialized constantpool in anFileInfo, constantPoolID is " << cpID; 584 UNREACHABLE(); 585 } 586 return JSHandle<JSTaggedValue>(uintptr_t(&iter->second)); 587} 588 589AOTFileManager::~AOTFileManager() 590{ 591 if (arkStackMapParser_ != nullptr) { 592 delete arkStackMapParser_; 593 arkStackMapParser_ = nullptr; 594 } 595} 596 597AOTFileManager::AOTFileManager(EcmaVM *vm) : vm_(vm), factory_(vm->GetFactory()) 598{ 599 bool enableLog = vm->GetJSOptions().WasSetCompilerLogOption(); 600 arkStackMapParser_ = new kungfu::ArkStackMapParser(enableLog); 601} 602 603JSTaggedValue AOTFileManager::GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal) 604{ 605 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 606 CString relativePath = ConvertToString(relativePathVal); 607 CString absPath; 608 if (!GetAbsolutePath(relativePath, absPath)) { 609 LOG_FULL(FATAL) << "Get Absolute Path failed"; 610 return JSTaggedValue::Hole(); 611 } 612 JSTaggedValue absPathVal = factory->NewFromUtf8(absPath).GetTaggedValue(); 613 return absPathVal; 614} 615 616bool AOTFileManager::GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr) 617{ 618 std::string relativePath = ConvertToStdString(relativePathCstr); 619 std::string absPath; 620 if (RealPath(relativePath, absPath)) { 621 absPathCstr = ConvertToString(absPath); 622 return true; 623 } 624 return false; 625} 626 627const Heap *AOTFileManager::GetHeap() 628{ 629 if (vm_ == nullptr) { 630 return nullptr; 631 } 632 return vm_->GetHeap(); 633} 634} // namespace panda::ecmascript 635