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