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