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