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 
26 namespace panda::ecmascript {
27 using CommonStubCSigns = kungfu::CommonStubCSigns;
28 using BytecodeStubCSigns = kungfu::BytecodeStubCSigns;
29 using SnapshotGlobalData = kungfu::SnapshotGlobalData;
30 
31 #if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
32 JsAotReaderCallback AOTFileManager::jsAotReader_ = nullptr;
33 #endif
34 
InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t capacity, uint32_t extraLength)35 void 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 
SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)43 void AOTLiteralInfo::SetObjectToCache(JSThread *thread, uint32_t index, JSTaggedValue value)
44 {
45     Set(thread, index, value);
46 }
47 
Iterate(const RootVisitor &v)48 void 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)
SetJsAotReader(JsAotReaderCallback cb)62 void AOTFileManager::SetJsAotReader(JsAotReaderCallback cb)
63 {
64     jsAotReader_ = cb;
65 }
66 
GetJsAotReader()67 JsAotReaderCallback AOTFileManager::GetJsAotReader()
68 {
69     return jsAotReader_;
70 }
71 #endif
72 
AOTFileExist(const std::string &aotFileName, const std::string &extension)73 bool 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 
DumpAOTInfo()83 void AOTFileManager::DumpAOTInfo()
84 {
85     AnFileDataManager *m = AnFileDataManager::GetInstance();
86     m->Dump();
87 }
88 
LoadStubFile(const std::string &fileName)89 void 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 
LoadAnFile(const std::string &fileName)100 bool 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 
LoadAiFile([[maybe_unused]] const std::string &filename)110 bool 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 
LoadAiFile(const JSPandaFile *jsPandaFile)124 bool 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 
GetAnFileInfo(const JSPandaFile *jsPandaFile) const160 const 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 
GetFileIndex(uint32_t anFileInfoIndex, CString abcNormalizedName) const170 uint32_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 
IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry) const190 bool 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 
GetPandaFiles(uint32_t aotFileInfoIndex)208 std::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 
BindPreloadedPandaFilesInAotFile(const std::string &moduleName)221 void 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 
HasPandaFile(uint32_t aotFileInfoIndex, const CString &abcNormalizedName) const243 bool 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 
BindPandaFileInAotFile(const std::string &aotFileBaseName, JSPandaFile *jsPandaFile) const253 void 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 
GetAnFileIndex(const JSPandaFile *jsPandaFile) const281 uint32_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 
TryReadLock()305 bool AOTFileManager::TryReadLock()
306 {
307     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
308     return anFileDataManager->SafeTryReadLock();
309 }
310 
IsEnableAOT() const311 bool AOTFileManager::IsEnableAOT() const
312 {
313     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
314     return anFileDataManager->IsEnable();
315 }
316 
InsideStub(uintptr_t pc)317 bool AOTFileManager::InsideStub(uintptr_t pc)
318 {
319     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
320     return anFileDataManager->SafeInsideStub(pc);
321 }
322 
InsideAOT(uintptr_t pc)323 bool AOTFileManager::InsideAOT(uintptr_t pc)
324 {
325     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
326     return anFileDataManager->SafeInsideAOT(pc);
327 }
328 
CalCallSiteInfo(uintptr_t retAddr, bool isDeopt)329 AOTFileInfo::CallSiteInfo AOTFileManager::CalCallSiteInfo(uintptr_t retAddr, bool isDeopt)
330 {
331     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
332     return anFileDataManager->SafeCalCallSiteInfo(retAddr, isDeopt);
333 }
334 
PrintAOTEntry(const JSPandaFile *file, const Method *method, uintptr_t entry)335 void 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 
SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc, const JSPandaFile *jsPandaFile, std::string_view entryPoint)344 void 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 
SetAOTFuncEntry(const JSPandaFile *jsPandaFile, JSFunction *function, Method *method, uint32_t entryIndex, bool *canFastCall)390 void 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 
GetStackMapParser() const423 kungfu::ArkStackMapParser *AOTFileManager::GetStackMapParser() const
424 {
425     return arkStackMapParser_;
426 }
427 
AdjustBCStubAndDebuggerStubEntries(JSThread *thread, const std::vector<AOTFileInfo::FuncEntryDes> &stubs, const AsmInterParsedOption &asmInterOpt)428 void 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 
InitializeStubEntries(const std::vector<AnFileInfo::FuncEntryDes> &stubs)454 void 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 
RewriteDataSection(uintptr_t dataSec, size_t size, uintptr_t newData, size_t newSize)501 bool 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 
ParseDeserializedData(const CString &snapshotFileName, JSTaggedValue deserializedData)510 void 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 
GetDeserializedConstantPool(const JSPandaFile *jsPandaFile, int32_t cpID)560 JSHandle<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 
~AOTFileManager()589 AOTFileManager::~AOTFileManager()
590 {
591     if (arkStackMapParser_ != nullptr) {
592         delete arkStackMapParser_;
593         arkStackMapParser_ = nullptr;
594     }
595 }
596 
AOTFileManager(EcmaVM *vm)597 AOTFileManager::AOTFileManager(EcmaVM *vm) : vm_(vm), factory_(vm->GetFactory())
598 {
599     bool enableLog = vm->GetJSOptions().WasSetCompilerLogOption();
600     arkStackMapParser_ = new kungfu::ArkStackMapParser(enableLog);
601 }
602 
GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal)603 JSTaggedValue 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 
GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr)616 bool 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 
GetHeap()627 const Heap *AOTFileManager::GetHeap()
628 {
629     if (vm_ == nullptr) {
630         return nullptr;
631     }
632     return vm_->GetHeap();
633 }
634 }  // namespace panda::ecmascript
635