• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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/aot_file_manager.h"
16 
17 #include "ecmascript/stackmap/ark_stackmap_parser.h"
18 #include "ecmascript/base/config.h"
19 #include "ecmascript/compiler/bc_call_signature.h"
20 #include "ecmascript/compiler/common_stubs.h"
21 #include "ecmascript/compiler/compiler_log.h"
22 #include "ecmascript/deoptimizer/deoptimizer.h"
23 #include "ecmascript/deoptimizer/relocator.h"
24 #include "ecmascript/ecma_vm.h"
25 #include "ecmascript/message_string.h"
26 #include "ecmascript/jspandafile/constpool_value.h"
27 #include "ecmascript/jspandafile/js_pandafile.h"
28 #include "ecmascript/jspandafile/program_object.h"
29 #include "ecmascript/js_file_path.h"
30 #include "ecmascript/js_runtime_options.h"
31 #include "ecmascript/js_thread.h"
32 #include "ecmascript/snapshot/mem/snapshot.h"
33 #include "ecmascript/stackmap/ark_stackmap_parser.h"
34 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
35 #include "ecmascript/mem/region.h"
36 #include "ecmascript/platform/elf.h"
37 #include "ecmascript/platform/file.h"
38 #include "ecmascript/platform/map.h"
39 
40 
41 extern const uint8_t _binary_stub_an_start[];
42 extern const uint32_t _binary_stub_an_length;
43 
44 namespace panda::ecmascript {
45 using CommonStubCSigns = kungfu::CommonStubCSigns;
46 using BytecodeStubCSigns = kungfu::BytecodeStubCSigns;
47 
SaveSectionsInfo(std::ofstream & file)48 void ModuleSectionDes::SaveSectionsInfo(std::ofstream &file)
49 {
50     uint32_t secInfoSize = GetSecInfosSize();
51     uint32_t secSize = 0;
52     file.write(reinterpret_cast<char *>(&secInfoSize), sizeof(secInfoSize));
53     std::multimap<std::string, double> SecMap;
54     for (auto &s : sectionsInfo_) {
55         uint8_t secName = static_cast<uint8_t>(s.first);
56         uint32_t curSecSize = GetSecSize(s.first);
57         uint64_t curSecAddr = GetSecAddr(s.first);
58         secSize += curSecSize;
59         SecMap.insert(make_pair(GetSecName(s.first), static_cast<double>(curSecSize)));
60         file.write(reinterpret_cast<char *>(&secName), sizeof(secName));
61         file.write(reinterpret_cast<char *>(&curSecSize), sizeof(curSecSize));
62         file.write(reinterpret_cast<char *>(curSecAddr), curSecSize);
63     }
64     std::shared_ptr<uint8_t> ptr = GetArkStackMapSharePtr();
65     uint32_t size = GetArkStackMapSize();
66     file.write(reinterpret_cast<char *>(&size), sizeof(size));
67     file.write(reinterpret_cast<char *>(ptr.get()), size);
68 
69     uint32_t index = GetStartIndex();
70     uint32_t cnt = GetFuncCount();
71     file.write(reinterpret_cast<char *>(&index), sizeof(index));
72     file.write(reinterpret_cast<char *>(&cnt), sizeof(cnt));
73     for (auto [key, val] : SecMap) {
74         LOG_COMPILER(DEBUG) << key << " size is "
75                             << std::fixed << std::setprecision(DECIMAL_LENS)
76                             << (val / 1_KB) << "KB "<< "percentage:"
77                             << std::fixed << std::setprecision(PERCENT_LENS)
78                             << val / secSize * HUNDRED_TIME << "% ";
79     }
80     LOG_COMPILER(DEBUG) << "elf secitions size = " << (secSize / 1_KB) << "KB"
81                         << ", ark stack map size = " << (size / 1_KB) << "KB";
82 }
83 
LoadStackMapSection(BinaryBufferParser & parser,uintptr_t secBegin,uint32_t & curUnitOffset)84 void ModuleSectionDes::LoadStackMapSection(BinaryBufferParser &parser, uintptr_t secBegin, uint32_t &curUnitOffset)
85 {
86     uint32_t size = 0;
87     parser.ParseBuffer(&size, sizeof(size));
88     parser.ParseBuffer(reinterpret_cast<void *>(secBegin), size);
89     SetArkStackMapSize(size);
90     SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secBegin));
91     curUnitOffset += size;
92     uint32_t index = 0;
93     uint32_t cnt = 0;
94     parser.ParseBuffer(&index, sizeof(index));
95     parser.ParseBuffer(&cnt, sizeof(cnt));
96     SetStartIndex(index);
97     SetFuncCount(cnt);
98 }
99 
LoadSectionsInfo(BinaryBufferParser & parser,uint32_t & curUnitOffset,uint64_t codeAddress)100 void ModuleSectionDes::LoadSectionsInfo(BinaryBufferParser &parser,
101     uint32_t &curUnitOffset, uint64_t codeAddress)
102 {
103     uint32_t secInfoSize = 0;
104     parser.ParseBuffer(&secInfoSize, sizeof(secInfoSize));
105     auto secBegin = codeAddress + static_cast<uintptr_t>(curUnitOffset);
106     for (uint8_t i = 0; i < secInfoSize; i++) {
107         uint8_t secName = 0;
108         parser.ParseBuffer(&secName, sizeof(secName));
109         auto secEnumName = static_cast<ElfSecName>(secName);
110         uint32_t secSize = 0;
111         parser.ParseBuffer(&secSize, sizeof(secSize));
112         SetSecSize(secSize, secEnumName);
113         parser.ParseBuffer(reinterpret_cast<void *>(secBegin), secSize);
114         curUnitOffset += secSize;
115         SetSecAddr(secBegin, secEnumName);
116         secBegin += secSize;
117     }
118     LoadStackMapSection(parser, secBegin, curUnitOffset);
119 }
120 
LoadStackMapSection(std::ifstream & file,uintptr_t secBegin,uint32_t & curUnitOffset)121 void ModuleSectionDes::LoadStackMapSection(std::ifstream &file, uintptr_t secBegin, uint32_t &curUnitOffset)
122 {
123     uint32_t size;
124     file.read(reinterpret_cast<char *>(&size), sizeof(size));
125     file.read(reinterpret_cast<char *>(secBegin), size);
126     SetArkStackMapSize(size);
127     SetArkStackMapPtr(reinterpret_cast<uint8_t *>(secBegin));
128     curUnitOffset += size;
129     uint32_t index;
130     uint32_t cnt;
131     file.read(reinterpret_cast<char *>(&index), sizeof(index));
132     file.read(reinterpret_cast<char *>(&cnt), sizeof(cnt));
133     SetStartIndex(index);
134     SetFuncCount(cnt);
135 }
136 
LoadSectionsInfo(std::ifstream & file,uint32_t & curUnitOffset,uint64_t codeAddress)137 void ModuleSectionDes::LoadSectionsInfo(std::ifstream &file,
138     uint32_t &curUnitOffset, uint64_t codeAddress)
139 {
140     uint32_t secInfoSize;
141     file.read(reinterpret_cast<char *>(&secInfoSize), sizeof(secInfoSize));
142     auto secBegin = codeAddress + static_cast<uintptr_t>(curUnitOffset);
143     for (uint8_t i = 0; i < secInfoSize; i++) {
144         uint8_t secName;
145         file.read(reinterpret_cast<char *>(&secName), sizeof(secName));
146         auto secEnumName = static_cast<ElfSecName>(secName);
147         uint32_t secSize;
148         file.read(reinterpret_cast<char *>(&secSize), sizeof(secSize));
149         SetSecSize(secSize, secEnumName);
150         file.read(reinterpret_cast<char *>(secBegin), secSize);
151         curUnitOffset += secSize;
152         SetSecAddr(secBegin, secEnumName);
153         secBegin += secSize;
154     }
155     LoadStackMapSection(file, secBegin, curUnitOffset);
156 }
157 
Save(const std::string & filename)158 void StubFileInfo::Save(const std::string &filename)
159 {
160     std::string realPath;
161     if (!RealPath(filename, realPath, false)) {
162         return;
163     }
164 
165     if (totalCodeSize_ == 0) {
166         LOG_COMPILER(FATAL) << "error: code size of generated stubs is empty!";
167     }
168 
169     std::ofstream file(realPath.c_str(), std::ofstream::binary);
170     SetStubNum(entries_.size());
171     file.write(reinterpret_cast<char *>(&entryNum_), sizeof(entryNum_));
172     file.write(reinterpret_cast<char *>(entries_.data()), sizeof(FuncEntryDes) * entryNum_);
173     uint32_t moduleNum = GetCodeUnitsNum();
174     file.write(reinterpret_cast<char *>(&moduleNum), sizeof(moduleNum_));
175     file.write(reinterpret_cast<char *>(&totalCodeSize_), sizeof(totalCodeSize_));
176     uint32_t asmStubSize = GetAsmStubSize();
177     file.write(reinterpret_cast<char *>(&asmStubSize), sizeof(asmStubSize));
178     uint64_t asmStubAddr = GetAsmStubAddr();
179     file.write(reinterpret_cast<char *>(asmStubAddr), asmStubSize);
180     for (size_t i = 0; i < moduleNum; i++) {
181         des_[i].SaveSectionsInfo(file);
182     }
183     file.close();
184 }
185 
Load()186 bool StubFileInfo::Load()
187 {
188     if (_binary_stub_an_length <= 1) {
189         LOG_FULL(FATAL) << "stub.an length <= 1, is default and invalid.";
190         return false;
191     }
192 
193     BinaryBufferParser binBufparser(const_cast<uint8_t *>(_binary_stub_an_start), _binary_stub_an_length);
194     binBufparser.ParseBuffer(&entryNum_, sizeof(entryNum_));
195     entries_.resize(entryNum_);
196     binBufparser.ParseBuffer(entries_.data(), sizeof(FuncEntryDes) * entryNum_);
197     binBufparser.ParseBuffer(&moduleNum_, sizeof(moduleNum_));
198     des_.resize(moduleNum_);
199     binBufparser.ParseBuffer(&totalCodeSize_, sizeof(totalCodeSize_));
200 
201     if (totalCodeSize_ == 0) {
202         LOG_COMPILER(ERROR) << "error: code in the binary stub is empty!";
203         return false;
204     }
205 
206     ExecutedMemoryAllocator::AllocateBuf(totalCodeSize_, exeMem_);
207     uint64_t codeAddress = reinterpret_cast<uint64_t>(exeMem_.addr_);
208     uint32_t curUnitOffset = 0;
209     uint32_t asmStubSize = 0;
210     binBufparser.ParseBuffer(&asmStubSize, sizeof(asmStubSize));
211     SetAsmStubSize(asmStubSize);
212     binBufparser.ParseBuffer(reinterpret_cast<void *>(codeAddress), asmStubSize);
213     SetAsmStubAddr(codeAddress);
214     curUnitOffset += asmStubSize;
215 
216     for (size_t i = 0; i < moduleNum_; i++) {
217         des_[i].LoadSectionsInfo(binBufparser, curUnitOffset, codeAddress);
218     }
219 
220     for (auto &entry : entries_) {
221         if (entry.IsGeneralRTStub()) {
222             uint64_t begin = GetAsmStubAddr();
223             entry.codeAddr_ += begin;
224         } else {
225             auto moduleDes = des_[entry.moduleIndex_];
226             entry.codeAddr_ += moduleDes.GetSecAddr(ElfSecName::TEXT);
227         }
228     }
229     LOG_COMPILER(INFO) << "loaded stub file successfully";
230     return true;
231 }
232 
Save(const std::string & filename,kungfu::Triple triple)233 void AnFileInfo::Save(const std::string &filename, kungfu::Triple triple)
234 {
235     std::string realPath;
236     if (!RealPath(filename, realPath, false)) {
237         return;
238     }
239 
240     if (totalCodeSize_ == 0) {
241         LOG_HOST_TOOL_ERROR << "The an file generated by the aot compiler is empty! "
242                             << "Maybe file in apPath is empty or all methods in ap file are mismatched";
243         LOG_COMPILER(FATAL) << "error: code size of generated an file is empty!";
244     }
245 
246     std::ofstream file(realPath.c_str(), std::ofstream::binary);
247     SetStubNum(entries_.size());
248 
249     Elf64_Ehdr header;
250     PackELFHeader(header, AOTFileManager::AOT_VERSION, triple);
251     file.write(reinterpret_cast<char *>(&header), sizeof(Elf64_Ehdr));
252     file.write(reinterpret_cast<char *>(&entryNum_), sizeof(entryNum_));
253     file.write(reinterpret_cast<char *>(entries_.data()), sizeof(FuncEntryDes) * entryNum_);
254     uint32_t moduleNum = GetCodeUnitsNum();
255     file.write(reinterpret_cast<char *>(&moduleNum), sizeof(moduleNum_));
256     file.write(reinterpret_cast<char *>(&totalCodeSize_), sizeof(totalCodeSize_));
257     LOG_COMPILER(DEBUG) << "total code size = " << (totalCodeSize_ / 1_KB) << "KB";
258     for (size_t i = 0; i < moduleNum; i++) {
259         des_[i].SaveSectionsInfo(file);
260     }
261     file.close();
262 }
263 
264 
RewriteRelcateDeoptHandler(EcmaVM * vm)265 void AnFileInfo::RewriteRelcateDeoptHandler([[maybe_unused]] EcmaVM *vm)
266 {
267 #if !WIN_OR_MAC_OR_IOS_PLATFORM
268     JSThread *thread = vm->GetJSThread();
269     uintptr_t patchAddr = thread->GetRTInterface(RTSTUB_ID(DeoptHandlerAsm));
270     RewriteRelcateTextSection(LLVM_DEOPT_RELOCATE_SYMBOL, patchAddr);
271 #endif
272 }
273 
RewriteRelcateTextSection(const char * symbol,uintptr_t patchAddr)274 void AnFileInfo::RewriteRelcateTextSection([[maybe_unused]] const char* symbol,
275     [[maybe_unused]] uintptr_t patchAddr)
276 {
277 #if !WIN_OR_MAC_OR_IOS_PLATFORM
278     for (auto &des: des_) {
279         uint32_t relaTextSize = des.GetSecSize(ElfSecName::RELATEXT);
280         if (relaTextSize != 0) {
281             uint64_t relatextAddr = des.GetSecAddr(ElfSecName::RELATEXT);
282             uint64_t textAddr = des.GetSecAddr(ElfSecName::TEXT);
283             uint64_t symTabAddr = des.GetSecAddr(ElfSecName::SYMTAB);
284             uint32_t symTabSize = des.GetSecSize(ElfSecName::SYMTAB);
285             uint32_t strTabSize = des.GetSecSize(ElfSecName::STRTAB);
286             uint64_t strTabAddr = des.GetSecAddr(ElfSecName::STRTAB);
287             RelocateTextInfo relaText = {textAddr, relatextAddr, relaTextSize};
288             SymAndStrTabInfo symAndStrTabInfo = {symTabAddr, symTabSize, strTabAddr, strTabSize};
289             Relocator relocate(relaText, symAndStrTabInfo);
290 #ifndef NDEBUG
291             relocate.DumpRelocateText();
292 #endif
293             relocate.RelocateBySymbol(symbol, patchAddr);
294         }
295     }
296 #endif
297 }
298 
Load(const std::string & filename)299 bool AnFileInfo::Load(const std::string &filename)
300 {
301     std::string realPath;
302     if (!RealPath(filename, realPath, false)) {
303         LOG_COMPILER(ERROR) << "Can not load aot file from path [ "  << filename << " ], "
304                             << "please execute ark_aot_compiler with options --aot-file.";
305         UNREACHABLE();
306         return false;
307     }
308 
309     std::ifstream file(realPath.c_str(), std::ofstream::binary);
310     if (!file.good()) {
311         LOG_COMPILER(INFO) << "Fail to load an file: " << realPath.c_str();
312         file.close();
313         return false;
314     }
315 
316     Elf64_Ehdr header;
317     file.read(reinterpret_cast<char *>(&header), sizeof(Elf64_Ehdr));
318     if (!VerifyELFHeader(header, AOTFileManager::AOT_VERSION)) {
319         file.close();
320         return false;
321     }
322 
323     file.read(reinterpret_cast<char *>(&entryNum_), sizeof(entryNum_));
324     entries_.resize(entryNum_);
325     file.read(reinterpret_cast<char *>(entries_.data()), sizeof(FuncEntryDes) * entryNum_);
326     file.read(reinterpret_cast<char *>(&moduleNum_), sizeof(moduleNum_));
327     des_.resize(moduleNum_);
328     file.read(reinterpret_cast<char *>(&totalCodeSize_), sizeof(totalCodeSize_));
329 
330     if (totalCodeSize_ == 0) {
331         file.close();
332         LOG_COMPILER(ERROR) << "error: code in the an file is empty!";
333         return false;
334     }
335     ExecutedMemoryAllocator::AllocateBuf(totalCodeSize_, exeMem_);
336     uint64_t codeAddress = reinterpret_cast<uint64_t>(exeMem_.addr_);
337     uint32_t curUnitOffset = 0;
338     for (size_t i = 0; i < moduleNum_; i++) {
339         des_[i].LoadSectionsInfo(file, curUnitOffset, codeAddress);
340     }
341 
342     for (size_t i = 0; i < entries_.size(); i++) {
343         FuncEntryDes& funcDes = entries_[i];
344         auto moduleDes = des_[funcDes.moduleIndex_];
345         funcDes.codeAddr_ += moduleDes.GetSecAddr(ElfSecName::TEXT);
346         if (funcDes.isMainFunc_) {
347             mainEntryMap_[funcDes.indexInKindOrMethodId_] = funcDes.codeAddr_;
348 #ifndef NDEBUG
349             LOG_COMPILER(INFO) << "AnFileInfo Load main method id: " << funcDes.indexInKindOrMethodId_
350                                << " code addr: " << reinterpret_cast<void*>(funcDes.codeAddr_);
351 #endif
352         }
353     }
354 
355     LOG_COMPILER(INFO) << "loaded an file: " << filename.c_str();
356     isLoad_ = true;
357     return true;
358 }
359 
IsLoadMain(const JSPandaFile * jsPandaFile,const CString & entry) const360 bool AnFileInfo::IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry) const
361 {
362     auto methodId = jsPandaFile->GetMainMethodIndex(entry);
363 #ifndef NDEBUG
364     LOG_COMPILER(INFO) << "AnFileInfo IsLoadMain method id: " << methodId << " entry: " << entry;
365 #endif
366     auto it = mainEntryMap_.find(methodId);
367     if (it == mainEntryMap_.end()) {
368         return false;
369     }
370     return true;
371 }
372 
Iterate(const RootVisitor & v)373 void AOTFileManager::Iterate(const RootVisitor &v)
374 {
375     for (auto &iter : desCPs_) {
376         for (auto &curCP : iter.second) {
377             v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&iter.second.at(curCP.first))));
378         }
379     }
380 }
381 
LoadStubFile(const std::string & fileName)382 void AOTFileManager::LoadStubFile(const std::string &fileName)
383 {
384     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
385     if (!anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::STUB)) {
386         return;
387     }
388     auto info = anFileDataManager->SafeGetStubFileInfo();
389     auto stubs = info->GetStubs();
390     InitializeStubEntries(stubs);
391 }
392 
LoadAnFile(const std::string & fileName)393 void AOTFileManager::LoadAnFile(const std::string &fileName)
394 {
395     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
396     if (!anFileDataManager->SafeLoad(fileName, AnFileDataManager::Type::AOT, vm_)) {
397         return;
398     }
399 }
400 
LoadAiFile(const std::string & filename)401 void AOTFileManager::LoadAiFile([[maybe_unused]] const std::string &filename)
402 {
403     Snapshot snapshot(vm_);
404 #if !WIN_OR_MAC_OR_IOS_PLATFORM
405     snapshot.Deserialize(SnapshotType::AI, filename.c_str());
406 #endif
407 }
408 
LoadAiFile(const JSPandaFile * jsPandaFile)409 void AOTFileManager::LoadAiFile(const JSPandaFile *jsPandaFile)
410 {
411     uint32_t anFileInfoIndex = GetAnFileIndex(jsPandaFile);
412     // this abc file does not have corresponding an file
413     if (anFileInfoIndex == INVALID_INDEX) {
414         return;
415     }
416 
417     auto iter = desCPs_.find(anFileInfoIndex);
418     // already loaded
419     if (iter != desCPs_.end()) {
420         return;
421     }
422 
423     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
424     std::string aiFilename = anFileDataManager->GetDir();
425     aiFilename += JSFilePath::GetHapName(jsPandaFile) + AOTFileManager::FILE_EXTENSION_AI;
426     LoadAiFile(aiFilename);
427 }
428 
429 
GetAnFileInfo(const JSPandaFile * jsPandaFile) const430 const std::shared_ptr<AnFileInfo> AOTFileManager::GetAnFileInfo(const JSPandaFile *jsPandaFile) const
431 {
432     uint32_t index = GetAnFileIndex(jsPandaFile);
433     if (index == JSPandaFile::INVALID_INDEX) {
434         return nullptr;
435     }
436     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
437     return anFileDataManager->SafeGetAnFileInfo(index);
438 }
439 
IsLoad(const JSPandaFile * jsPandaFile) const440 bool AOTFileManager::IsLoad(const JSPandaFile *jsPandaFile) const
441 {
442     if (!AnFileDataManager::GetInstance()->IsEnable()) {
443         return false;
444     }
445 
446     const std::shared_ptr<AnFileInfo> anFileInfo = GetAnFileInfo(jsPandaFile);
447     if (anFileInfo == nullptr) {
448         return false;
449     }
450     return anFileInfo->IsLoad();
451 }
452 
IsLoadMain(const JSPandaFile * jsPandaFile,const CString & entry) const453 bool AOTFileManager::IsLoadMain(const JSPandaFile *jsPandaFile, const CString &entry) const
454 {
455     if (!jsPandaFile->IsLoadedAOT()) {
456         return false;
457     }
458 
459     const std::shared_ptr<AnFileInfo> anFileInfo = GetAnFileInfo(jsPandaFile);
460     if (anFileInfo == nullptr) {
461         return false;
462     }
463 
464     return anFileInfo->IsLoadMain(jsPandaFile, entry);
465 }
466 
GetAnFileIndex(const JSPandaFile * jsPandaFile) const467 uint32_t AOTFileManager::GetAnFileIndex(const JSPandaFile *jsPandaFile) const
468 {
469     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
470 
471     // run via command line
472     if (vm_->GetJSOptions().WasAOTOutputFileSet()) {
473         std::string jsPandaFileDesc = jsPandaFile->GetJSPandaFileDesc().c_str();
474         std::string baseName = JSFilePath::GetFileName(jsPandaFileDesc);
475         if (baseName.empty()) {
476             return JSPandaFile::INVALID_INDEX;
477         }
478         std::string anFileName = baseName + FILE_EXTENSION_AN;
479         return anFileDataManager->SafeGetFileInfoIndex(anFileName);
480     }
481 
482     // run from app hap
483     std::string hapName = JSFilePath::GetHapName(jsPandaFile);
484     if (hapName.empty()){
485         return JSPandaFile::INVALID_INDEX;
486     }
487     std::string anFileName = hapName + FILE_EXTENSION_AN;
488     return anFileDataManager->SafeGetFileInfoIndex(anFileName);
489 }
490 
TryReadLock() const491 bool AOTFileManager::TryReadLock() const
492 {
493     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
494     return anFileDataManager->SafeTryReadLock();
495 }
496 
InsideStub(uintptr_t pc) const497 bool AOTFileManager::InsideStub(uintptr_t pc) const
498 {
499     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
500     return anFileDataManager->SafeInsideStub(pc);
501 }
502 
InsideAOT(uintptr_t pc) const503 bool AOTFileManager::InsideAOT(uintptr_t pc) const
504 {
505     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
506     return anFileDataManager->SafeInsideAOT(pc);
507 }
508 
CalCallSiteInfo(uintptr_t retAddr) const509 AOTFileInfo::CallSiteInfo AOTFileManager::CalCallSiteInfo(uintptr_t retAddr) const
510 {
511     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
512     return anFileDataManager->SafeCalCallSiteInfo(retAddr);
513 
514 }
515 
PrintAOTEntry(const JSPandaFile * file,const Method * method,uintptr_t entry)516 void AOTFileManager::PrintAOTEntry(const JSPandaFile *file, const Method *method, uintptr_t entry)
517 {
518     uint32_t mId = method->GetMethodId().GetOffset();
519     std::string mName = method->GetMethodName(file);
520     std::string fileName = file->GetFileName();
521     LOG_COMPILER(INFO) << "Bind " << mName << "@" << mId << "@" << fileName
522                        << " -> AOT-Entry = " << reinterpret_cast<void*>(entry);
523 }
524 
SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc,const JSPandaFile * jsPandaFile,std::string_view entryPoint)525 void AOTFileManager::SetAOTMainFuncEntry(JSHandle<JSFunction> mainFunc, const JSPandaFile *jsPandaFile,
526                                      std::string_view entryPoint)
527 {
528     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
529     uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex();
530     const std::shared_ptr<AnFileInfo> anFileInfo = anFileDataManager->SafeGetAnFileInfo(anFileInfoIndex);
531     // get main func method
532     auto mainFuncMethodId = jsPandaFile->GetMainMethodIndex(entryPoint.data());
533     auto mainEntry = anFileInfo->GetMainFuncEntry(mainFuncMethodId);
534     MethodLiteral *mainMethod = jsPandaFile->FindMethodLiteral(mainFuncMethodId);
535     mainMethod->SetAotCodeBit(true);
536     mainMethod->SetNativeBit(false);
537     Method *method = mainFunc->GetCallTarget();
538     method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold());
539     method->SetCodeEntryAndMarkAOT(reinterpret_cast<uintptr_t>(mainEntry));
540 #ifndef NDEBUG
541     PrintAOTEntry(jsPandaFile, method, mainEntry);
542 #endif
543 }
544 
SetAOTFuncEntry(const JSPandaFile * jsPandaFile,Method * method,uint32_t entryIndex)545 void AOTFileManager::SetAOTFuncEntry(const JSPandaFile *jsPandaFile, Method *method, uint32_t entryIndex)
546 {
547     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
548     uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex();
549     const std::shared_ptr<AnFileInfo> anFileInfo = anFileDataManager->SafeGetAnFileInfo(anFileInfoIndex);
550     const AOTFileInfo::FuncEntryDes &entry = anFileInfo->GetStubDes(entryIndex);
551     uint64_t codeEntry = entry.codeAddr_;
552 #ifndef NDEBUG
553     PrintAOTEntry(jsPandaFile, method, codeEntry);
554 #endif
555     if (!codeEntry) {
556         return;
557     }
558     method->SetDeoptThreshold(vm_->GetJSOptions().GetDeoptThreshold());
559     method->SetCodeEntryAndMarkAOT(codeEntry);
560 }
561 
SetAOTFuncEntryForLiteral(const JSPandaFile * jsPandaFile,const TaggedArray * literal,const AOTLiteralInfo * entryIndexes)562 void AOTFileManager::SetAOTFuncEntryForLiteral(const JSPandaFile *jsPandaFile, const TaggedArray *literal,
563                                                const AOTLiteralInfo *entryIndexes)
564 {
565     size_t elementsLen = literal->GetLength();
566     JSTaggedValue value = JSTaggedValue::Undefined();
567     int pos = 0;
568     for (size_t i = 0; i < elementsLen; i++) {
569         value = literal->Get(i);
570         if (value.IsJSFunction()) {
571             JSTaggedValue index = entryIndexes->Get(pos++);
572             int entryIndex = index.GetInt();
573             // -1 : this jsfunction is a large function
574             if (entryIndex == -1) {
575                 continue;
576             }
577             SetAOTFuncEntry(jsPandaFile, JSFunction::Cast(value)->GetCallTarget(), static_cast<uint32_t>(entryIndex));
578         }
579     }
580 }
581 
GetStackMapParser() const582 kungfu::ArkStackMapParser* AOTFileManager::GetStackMapParser() const
583 {
584     return arkStackMapParser_;
585 }
586 
AdjustBCStubAndDebuggerStubEntries(JSThread * thread,const std::vector<AOTFileInfo::FuncEntryDes> & stubs,const AsmInterParsedOption & asmInterOpt)587 void AOTFileManager::AdjustBCStubAndDebuggerStubEntries(JSThread *thread,
588     const std::vector<AOTFileInfo::FuncEntryDes> &stubs,
589     const AsmInterParsedOption &asmInterOpt)
590 {
591     auto defaultBCStubDes = stubs[BytecodeStubCSigns::SingleStepDebugging];
592     auto defaultBCDebuggerStubDes = stubs[BytecodeStubCSigns::BCDebuggerEntry];
593     auto defaultBCDebuggerExceptionStubDes = stubs[BytecodeStubCSigns::BCDebuggerExceptionEntry];
594     ASSERT(defaultBCStubDes.kind_ == CallSignature::TargetKind::BYTECODE_HELPER_HANDLER);
595     if (asmInterOpt.handleStart >= 0 && asmInterOpt.handleStart <= asmInterOpt.handleEnd) {
596         for (int i = asmInterOpt.handleStart; i <= asmInterOpt.handleEnd; i++) {
597             thread->SetBCStubEntry(static_cast<size_t>(i), defaultBCStubDes.codeAddr_);
598         }
599 #define DISABLE_SINGLE_STEP_DEBUGGING(name) \
600         thread->SetBCStubEntry(BytecodeStubCSigns::ID_##name, stubs[BytecodeStubCSigns::ID_##name].codeAddr_);
601         INTERPRETER_DISABLE_SINGLE_STEP_DEBUGGING_BC_STUB_LIST(DISABLE_SINGLE_STEP_DEBUGGING)
602 #undef DISABLE_SINGLE_STEP_DEBUGGING
603     }
604     for (size_t i = 0; i < BCStubEntries::EXISTING_BC_HANDLER_STUB_ENTRIES_COUNT; i++) {
605         if (i == BytecodeStubCSigns::ID_ExceptionHandler) {
606             thread->SetBCDebugStubEntry(i, defaultBCDebuggerExceptionStubDes.codeAddr_);
607             continue;
608         }
609         thread->SetBCDebugStubEntry(i, defaultBCDebuggerStubDes.codeAddr_);
610     }
611 }
612 
InitializeStubEntries(const std::vector<AnFileInfo::FuncEntryDes> & stubs)613 void AOTFileManager::InitializeStubEntries(const std::vector<AnFileInfo::FuncEntryDes>& stubs)
614 {
615     auto thread = vm_->GetAssociatedJSThread();
616     for (size_t i = 0; i < stubs.size(); i++) {
617         auto des = stubs[i];
618         if (des.IsCommonStub()) {
619             thread->SetFastStubEntry(des.indexInKindOrMethodId_, des.codeAddr_);
620         } else if (des.IsBCStub()) {
621             thread->SetBCStubEntry(des.indexInKindOrMethodId_, des.codeAddr_);
622 #if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG
623             auto start = GET_MESSAGE_STRING_ID(HandleLdundefined);
624             std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start);
625             LOG_ECMA(DEBUG) << "bytecode index: " << des.indexInKindOrMethodId_ << " :" << format
626                 << " addr: 0x" << std::hex << des.codeAddr_;
627 #endif
628         } else if (des.IsBuiltinsStub()) {
629             thread->SetBuiltinStubEntry(des.indexInKindOrMethodId_, des.codeAddr_);
630 #if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG
631             int start = GET_MESSAGE_STRING_ID(CharCodeAt);
632             std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start - 1);  // -1: NONE
633             LOG_ECMA(DEBUG) << "builtins index: " << std::dec << des.indexInKindOrMethodId_ << " :" << format
634                 << " addr: 0x" << std::hex << des.codeAddr_;
635 #endif
636         } else {
637             thread->RegisterRTInterface(des.indexInKindOrMethodId_, des.codeAddr_);
638 #if ECMASCRIPT_ENABLE_ASM_FILE_LOAD_LOG
639                 int start = GET_MESSAGE_STRING_ID(CallRuntime);
640                 std::string format = MessageString::GetMessageString(des.indexInKindOrMethodId_ + start);
641                 LOG_ECMA(DEBUG) << "runtime index: " << std::dec << des.indexInKindOrMethodId_ << " :" << format
642                     << " addr: 0x" << std::hex << des.codeAddr_;
643 #endif
644         }
645     }
646     AsmInterParsedOption asmInterOpt = vm_->GetJSOptions().GetAsmInterParsedOption();
647     AdjustBCStubAndDebuggerStubEntries(thread, stubs, asmInterOpt);
648 }
649 
RewriteDataSection(uintptr_t dataSec,size_t size,uintptr_t newData,size_t newSize)650 bool AOTFileManager::RewriteDataSection(uintptr_t dataSec, size_t size,
651     uintptr_t newData, size_t newSize)
652 {
653     if (memcpy_s(reinterpret_cast<void *>(dataSec), size,
654                  reinterpret_cast<void *>(newData), newSize) != EOK) {
655         LOG_FULL(FATAL) << "memset failed";
656         return false;
657     }
658     return true;
659 }
660 
AddConstantPool(const CString & snapshotFileName,JSTaggedValue deserializedCPList)661 void AOTFileManager::AddConstantPool(const CString &snapshotFileName, JSTaggedValue deserializedCPList)
662 {
663     AnFileDataManager *anFileDataManager = AnFileDataManager::GetInstance();
664     std::string baseName = JSFilePath::GetFileName(snapshotFileName.c_str());
665     uint32_t anFileInfoIndex = anFileDataManager->SafeGetFileInfoIndex(baseName + FILE_EXTENSION_AN);
666 
667     desCPs_.insert({anFileInfoIndex, CMap<int32_t, JSTaggedValue>{}});
668     CMap<int32_t, JSTaggedValue> &cpMap = desCPs_[anFileInfoIndex];
669 
670     JSHandle<TaggedArray> cpList(vm_->GetJSThread(), deserializedCPList);
671     uint32_t len = cpList->GetLength();
672     for (uint32_t pos = 0; pos < len; pos += DESERI_CP_ITEM_SIZE) {
673         int32_t constantPoolID = cpList->Get(pos).GetInt();
674         JSTaggedValue cp = cpList->Get(pos + 1);
675         cpMap.insert({constantPoolID, cp});
676     }
677 }
678 
GetDeserializedConstantPool(const JSPandaFile * jsPandaFile,int32_t cpID)679 JSHandle<JSTaggedValue> AOTFileManager::GetDeserializedConstantPool(const JSPandaFile *jsPandaFile, int32_t cpID)
680 {
681     //The deserialization of the 'ai' data used by the multi-work
682     // is not implemented yet, so there may be a case where
683     // desCPs_ is empty, in which case the Hole will be returned
684     if (desCPs_.size() == 0) {
685         return JSHandle<JSTaggedValue>(vm_->GetJSThread(), JSTaggedValue::Hole());
686     }
687     uint32_t anFileInfoIndex = jsPandaFile->GetAOTFileInfoIndex();
688     CMap<int32_t, JSTaggedValue> &cpMap = desCPs_.at(anFileInfoIndex);
689     auto iter = cpMap.find(cpID);
690     if (iter == cpMap.end()) {
691         LOG_COMPILER(FATAL) << "can not find deserialized constantpool in anFileInfo, constantPoolID is " << cpID;
692         UNREACHABLE();
693     }
694     return JSHandle<JSTaggedValue>(uintptr_t(&iter->second));
695 }
696 
~AOTFileManager()697 AOTFileManager::~AOTFileManager()
698 {
699     if (arkStackMapParser_ != nullptr) {
700         delete arkStackMapParser_;
701         arkStackMapParser_ = nullptr;
702     }
703 }
704 
AOTFileManager(EcmaVM * vm)705 AOTFileManager::AOTFileManager(EcmaVM *vm) : vm_(vm), factory_(vm->GetFactory())
706 {
707     bool enableLog = vm->GetJSOptions().WasSetCompilerLogOption();
708     arkStackMapParser_ = new kungfu::ArkStackMapParser(enableLog);
709 }
710 
GetAbsolutePath(JSThread * thread,JSTaggedValue relativePathVal)711 JSTaggedValue AOTFileManager::GetAbsolutePath(JSThread *thread, JSTaggedValue relativePathVal)
712 {
713     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
714     CString relativePath = ConvertToString(relativePathVal);
715     CString absPath;
716     if (!GetAbsolutePath(relativePath, absPath)) {
717         LOG_FULL(FATAL) << "Get Absolute Path failed";
718         return JSTaggedValue::Hole();
719     }
720     JSTaggedValue absPathVal = factory->NewFromUtf8(absPath).GetTaggedValue();
721     return absPathVal;
722 }
723 
GetAbsolutePath(const CString & relativePathCstr,CString & absPathCstr)724 bool AOTFileManager::GetAbsolutePath(const CString &relativePathCstr, CString &absPathCstr)
725 {
726     std::string relativePath = CstringConvertToStdString(relativePathCstr);
727     std::string absPath = "";
728     if (RealPath(relativePath, absPath)) {
729         absPathCstr = ConvertToString(absPath);
730         return true;
731     }
732     return false;
733 }
734 
ParseBuffer(void * dst,uint32_t count)735 void BinaryBufferParser::ParseBuffer(void *dst, uint32_t count)
736 {
737     if (count > 0 && count + offset_ <= length_) {
738         if (memcpy_s(dst, count, buffer_ + offset_, count) != EOK) {
739             LOG_FULL(FATAL) << "memcpy_s failed";
740         }
741         offset_ = offset_ + count;
742     } else {
743         LOG_FULL(FATAL) << "parse buffer error, length is 0 or overflow";
744     }
745 }
746 
ParseBuffer(uint8_t * dst,uint32_t count,uint8_t * src)747 void BinaryBufferParser::ParseBuffer(uint8_t *dst, uint32_t count, uint8_t *src)
748 {
749     if (src >= buffer_ && src + count <= buffer_ + length_) {
750         if (memcpy_s(dst, count, src, count) != EOK) {
751             LOG_FULL(FATAL) << "memcpy_s failed";
752         }
753     } else {
754         LOG_FULL(FATAL) << "parse buffer error, length is 0 or overflow";
755     }
756 }
757 
CalCallSiteInfo(uintptr_t retAddr,std::tuple<uint64_t,uint8_t *,int,kungfu::CalleeRegAndOffsetVec> & ret) const758 bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr,
759     std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec>& ret) const
760 {
761     uint64_t textStart = 0;
762     uint8_t *stackmapAddr = nullptr;
763     int delta = 0;
764     auto& des = GetCodeUnits();
765     auto& funcEntryDes = GetStubs();
766 
767     auto cmp = [](const AOTFileInfo::FuncEntryDes &a, const AOTFileInfo::FuncEntryDes &b) {
768                     return a.codeAddr_ < b.codeAddr_;
769                 };
770     for (size_t i = 0; i < des.size(); i++) {
771         auto d = des[i];
772         uint64_t addr = d.GetSecAddr(ElfSecName::TEXT);
773         uint32_t size = d.GetSecSize(ElfSecName::TEXT);
774         if (retAddr < addr || retAddr >= addr + size) {
775             continue;
776         }
777         stackmapAddr = d.GetArkStackMapRawPtr();
778         ASSERT(stackmapAddr != nullptr);
779         textStart = addr;
780         auto startIndex = d.GetStartIndex();
781         auto funcCount = d.GetFuncCount();
782         auto s = funcEntryDes.begin() + startIndex;
783         auto t = funcEntryDes.begin() + startIndex + funcCount;
784         AOTFileInfo::FuncEntryDes target;
785         target.codeAddr_ = retAddr - 1; // -1: for pc
786         auto it = std::upper_bound(s, t, target, cmp);
787         --it;
788         ASSERT(it != t);
789         ASSERT((it->codeAddr_ <= target.codeAddr_) && (target.codeAddr_ < it->codeAddr_ + it->funcSize_));
790         delta = it->fpDeltaPrevFrameSp_;
791         kungfu::CalleeRegAndOffsetVec calleeRegInfo;
792         for (uint32_t j = 0; j < it->calleeRegisterNum_; j++) {
793             kungfu::DwarfRegType reg = static_cast<kungfu::DwarfRegType>(it->CalleeReg2Offset_[2 * j]);
794             kungfu::OffsetType offset = static_cast<kungfu::OffsetType>(it->CalleeReg2Offset_[2 * j + 1]);
795             kungfu::DwarfRegAndOffsetType regAndOffset = std::make_pair(reg, offset);
796             calleeRegInfo.emplace_back(regAndOffset);
797         }
798         ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
799         return true;
800     }
801     return false;
802 }
803 
GetInstance()804 AnFileDataManager *AnFileDataManager::GetInstance()
805 {
806     static AnFileDataManager AnFileDataManager;
807     return &AnFileDataManager;
808 }
809 
~AnFileDataManager()810 AnFileDataManager::~AnFileDataManager()
811 {
812     SafeDestoryAllData();
813 }
814 
SafeDestoryAllData()815 void AnFileDataManager::SafeDestoryAllData()
816 {
817     os::memory::WriteLockHolder lock(lock_);
818     if (loadedStub_ != nullptr) {
819         ExecutedMemoryAllocator::DestoryBuf(loadedStub_->GetExeMem());
820         loadedStub_ = nullptr;
821     }
822 
823     for (auto &iter : loadedAn_) {
824         ExecutedMemoryAllocator::DestoryBuf(iter->GetExeMem());
825     }
826     loadedAn_.clear();
827 }
828 
SafeLoad(const std::string & fileName,Type type,EcmaVM * vm)829 bool AnFileDataManager::SafeLoad(const std::string &fileName, Type type, EcmaVM* vm)
830 {
831     os::memory::WriteLockHolder lock(lock_);
832     if (type == Type::STUB) {
833         if (loadedStub_ != nullptr) {
834                 return true;
835             }
836         return UnsafeLoadFromStub();
837     } else {
838         const std::shared_ptr<const AOTFileInfo> aotFileInfo = UnsafeFind(fileName);
839         if (aotFileInfo != nullptr) {
840             return true;
841         }
842         return UnsafeLoadFromAOT(fileName, vm);
843     }
844 }
845 
UnsafeFind(const std::string & fileName) const846 std::shared_ptr<AnFileInfo> AnFileDataManager::UnsafeFind(const std::string &fileName) const
847 {
848     // note: This method is not thread-safe
849     // need to ensure that the instance of AnFileDataManager has been locked before use
850     const auto iter = anFileNameToIndexMap_.find(fileName);
851     if (iter == anFileNameToIndexMap_.end()) {
852         return nullptr;
853     }
854     uint32_t index = iter->second;
855     return loadedAn_.at(index);
856 }
857 
UnsafeLoadFromStub()858 bool AnFileDataManager::UnsafeLoadFromStub()
859 {
860     // note: This method is not thread-safe
861     // need to ensure that the instance of AnFileDataManager has been locked before use
862     loadedStub_ = std::make_shared<StubFileInfo>(StubFileInfo());
863     if (!loadedStub_->Load()) {
864         return false;
865     }
866     return true;
867 }
868 
UnsafeLoadFromAOT(const std::string & fileName,EcmaVM * vm)869 bool AnFileDataManager::UnsafeLoadFromAOT(const std::string &fileName, EcmaVM *vm)
870 {
871     // note: This method is not thread-safe
872     // need to ensure that the instance of AnFileDataManager has been locked before use
873     std::shared_ptr<AnFileInfo> info = std::make_shared<AnFileInfo>(AnFileInfo());
874     if (!info->Load(fileName)) {
875         return false;
876     }
877     info->RewriteRelcateDeoptHandler(vm);
878     std::string anBasename = JSFilePath::GetBaseName(fileName);
879     anFileNameToIndexMap_.insert({anBasename, loadedAn_.size()});
880     loadedAn_.emplace_back(info);
881     return true;
882 }
883 
SafeGetFileInfoIndex(const std::string & fileName)884 uint32_t AnFileDataManager::SafeGetFileInfoIndex(const std::string &fileName)
885 {
886     os::memory::ReadLockHolder lock(lock_);
887     auto iter = anFileNameToIndexMap_.find(fileName);
888     if (iter == anFileNameToIndexMap_.end()) {
889         return JSPandaFile::INVALID_INDEX;
890     }
891     return anFileNameToIndexMap_.at(fileName);
892 }
893 
SafeGetAnFileInfo(uint32_t index)894 std::shared_ptr<AnFileInfo> AnFileDataManager::SafeGetAnFileInfo(uint32_t index)
895 {
896     os::memory::ReadLockHolder lock(lock_);
897     return loadedAn_.at(index);
898 }
899 
SafeGetStubFileInfo()900 std::shared_ptr<StubFileInfo> AnFileDataManager::SafeGetStubFileInfo()
901 {
902     os::memory::ReadLockHolder lock(lock_);
903     return loadedStub_;
904 }
905 
906 // Using for cpuprofiler to check if the ReadLock can be held in singal handler, to avoid the reentrancy deadlock.
SafeTryReadLock()907 bool AnFileDataManager::SafeTryReadLock()
908 {
909     // Try to acquire the lock when the signal callback starts to execute. At this time, the vm thread is interrupted,
910     // so the status of whether the lock is held by vm thread will not change until the signal callback ends. If the
911     // attempt is successful, it means that the current vm thread does not hold the lock,the reentrancy problem will
912     // not occur in the callback.
913     if (lock_.TryReadLock()) {
914         lock_.Unlock();
915         return true;
916     }
917     return false;
918 }
919 
SafeInsideStub(uintptr_t pc)920 bool AnFileDataManager::SafeInsideStub(uintptr_t pc)
921 {
922     os::memory::ReadLockHolder lock(lock_);
923     if (loadedStub_ == nullptr) {
924         LOG_COMPILER(ERROR) << "SafeInsideStub: The stub file is not loaded.";
925         return false;
926     }
927 
928     uint64_t stubStartAddr = loadedStub_->GetAsmStubAddr();
929     uint64_t stubEndAddr = stubStartAddr + loadedStub_->GetAsmStubSize();
930     if (pc >= stubStartAddr && pc <= stubEndAddr) {
931         return true;
932     }
933 
934     const std::vector<ModuleSectionDes> &des = loadedStub_->GetCodeUnits();
935     for (auto &curDes : des) {
936         if (curDes.ContainCode(pc)) {
937             return true;
938         }
939     }
940 
941     return false;
942 }
943 
SafeInsideAOT(uintptr_t pc)944 bool AnFileDataManager::SafeInsideAOT(uintptr_t pc)
945 {
946     os::memory::ReadLockHolder lock(lock_);
947     for (auto &info : loadedAn_) {
948         const std::vector<ModuleSectionDes> &des = info->GetCodeUnits();
949         for (auto &curDes : des) {
950             if (curDes.ContainCode(pc)) {
951                 return true;
952             }
953         }
954     }
955     return false;
956 }
957 
SafeCalCallSiteInfo(uintptr_t retAddr)958 AOTFileInfo::CallSiteInfo AnFileDataManager::SafeCalCallSiteInfo(uintptr_t retAddr)
959 {
960     os::memory::ReadLockHolder lock(lock_);
961     AOTFileInfo::CallSiteInfo callsiteInfo;
962     bool ans = loadedStub_->CalCallSiteInfo(retAddr, callsiteInfo);
963     if (ans) {
964         return callsiteInfo;
965     }
966     // aot
967     for (auto &info : loadedAn_) {
968         ans = info->CalCallSiteInfo(retAddr, callsiteInfo);
969         if (ans) {
970             return callsiteInfo;
971         }
972     }
973     return callsiteInfo;
974 }
975 }
976