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