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