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