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