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