• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 
16 #include "ecmascript/ecma_context.h"
17 
18 #include "ecmascript/base/path_helper.h"
19 #include "ecmascript/builtins/builtins.h"
20 #include "ecmascript/builtins/builtins_global.h"
21 #include "ecmascript/builtins/builtins_regexp.h"
22 #include "ecmascript/builtins/builtins_number.h"
23 #include "ecmascript/builtins/builtins_string.h"
24 #include "ecmascript/compiler/aot_file/an_file_data_manager.h"
25 #include "ecmascript/compiler/common_stubs.h"
26 #include "ecmascript/ecma_string_table.h"
27 #include "ecmascript/ecma_vm.h"
28 #include "ecmascript/global_env.h"
29 #include "ecmascript/global_env_constants-inl.h"
30 #include "ecmascript/interpreter/interpreter-inl.h"
31 #include "ecmascript/jobs/micro_job_queue.h"
32 #include "ecmascript/jspandafile/js_pandafile.h"
33 #include "ecmascript/jspandafile/js_pandafile_manager.h"
34 #include "ecmascript/jspandafile/program_object.h"
35 #include "ecmascript/js_function.h"
36 #include "ecmascript/js_thread.h"
37 #include "ecmascript/log.h"
38 #include "ecmascript/module/module_path_helper.h"
39 #include "ecmascript/object_factory.h"
40 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
41 #include "ecmascript/require/js_cjs_module_cache.h"
42 #include "ecmascript/require/js_require_manager.h"
43 #include "ecmascript/snapshot/mem/snapshot.h"
44 #include "ecmascript/platform/log.h"
45 #include "ecmascript/global_index_map.h"
46 
47 namespace panda::ecmascript {
48 using PathHelper = base::PathHelper;
49 
EcmaContext(JSThread * thread)50 EcmaContext::EcmaContext(JSThread *thread)
51     : thread_(thread),
52       vm_(thread->GetEcmaVM()),
53       factory_(vm_->GetFactory())
54 {
55 }
56 
57 /* static */
Create(JSThread * thread)58 EcmaContext *EcmaContext::Create(JSThread *thread)
59 {
60     LOG_ECMA(INFO) << "EcmaContext::Create";
61     auto context = new EcmaContext(thread);
62     if (UNLIKELY(context == nullptr)) {
63         LOG_ECMA(ERROR) << "Failed to create ecma context";
64         return nullptr;
65     }
66     return context;
67 }
68 
69 // static
Destroy(EcmaContext * context)70 bool EcmaContext::Destroy(EcmaContext *context)
71 {
72     if (context != nullptr) {
73         delete context;
74         context = nullptr;
75         return true;
76     }
77     return false;
78 }
79 
SetTSManager(TSManager * set)80 void EcmaContext::SetTSManager(TSManager *set)
81 {
82     if (tsManager_ != nullptr) {
83         delete tsManager_;
84     }
85     tsManager_ = set;
86 }
87 
Initialize()88 bool EcmaContext::Initialize()
89 {
90     LOG_ECMA(DEBUG) << "EcmaContext::Initialize";
91     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "EcmaContext::Initialize");
92     [[maybe_unused]] EcmaHandleScope scope(thread_);
93     aotFileManager_ = new AOTFileManager(vm_);
94     propertiesCache_ = new PropertiesCache();
95     regExpParserCache_ = new RegExpParserCache();
96 
97     JSHandle<JSHClass> hClassHandle = factory_->InitClassClass();
98 
99     JSHandle<JSHClass> globalEnvClass = factory_->NewEcmaHClass(
100         *hClassHandle,
101         GlobalEnv::SIZE,
102         JSType::GLOBAL_ENV);
103     thread_->SetGlobalConst(&globalConst_);
104     globalConst_.Init(thread_, *hClassHandle);
105     auto arrayHClassIndexMaps = Elements::InitializeHClassMap();
106     thread_->SetArrayHClassIndexMap(arrayHClassIndexMaps);
107 
108     JSHandle<GlobalEnv> globalEnv = factory_->NewGlobalEnv(*globalEnvClass);
109     globalEnv->Init(thread_);
110     globalEnv_ = globalEnv.GetTaggedValue();
111     Builtins builtins;
112     bool builtinsLazyEnabled = vm_->GetJSOptions().IsWorker() && vm_->GetJSOptions().GetEnableBuiltinsLazy();
113     thread_->SetEnableLazyBuiltins(builtinsLazyEnabled);
114     builtins.Initialize(globalEnv, thread_, builtinsLazyEnabled);
115 
116     SetupRegExpResultCache();
117     SetupRegExpGlobalResult();
118     SetupNumberToStringResultCache();
119     SetupStringSplitResultCache();
120     SetupStringToListResultCache();
121     microJobQueue_ = factory_->NewMicroJobQueue().GetTaggedValue();
122     moduleManager_ = new ModuleManager(vm_);
123     tsManager_ = new TSManager(vm_);
124     ptManager_ = new kungfu::PGOTypeManager(vm_);
125     optCodeProfiler_ = new OptCodeProfiler();
126     if (vm_->GetJSOptions().GetTypedOpProfiler()) {
127         typedOpProfiler_ = new TypedOpProfiler();
128     }
129     initialized_ = true;
130     return true;
131 }
132 
InitializeEcmaScriptRunStat()133 void EcmaContext::InitializeEcmaScriptRunStat()
134 {
135     // NOLINTNEXTLINE(modernize-avoid-c-arrays)
136     static const char *runtimeCallerNames[] = {
137 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
138 #define INTERPRETER_CALLER_NAME(name) "Interpreter::" #name,
139     INTERPRETER_CALLER_LIST(INTERPRETER_CALLER_NAME)  // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
140 #undef INTERPRETER_CALLER_NAME
141 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
142 #define BUILTINS_API_NAME(class, name) "BuiltinsApi::" #class "_" #name,
143     BUILTINS_API_LIST(BUILTINS_API_NAME)
144 #undef BUILTINS_API_NAME
145 #define ABSTRACT_OPERATION_NAME(class, name) "AbstractOperation::" #class "_" #name,
146     ABSTRACT_OPERATION_LIST(ABSTRACT_OPERATION_NAME)
147 #undef ABSTRACT_OPERATION_NAME
148 #define MEM_ALLOCATE_AND_GC_NAME(name) "Memory::" #name,
149     MEM_ALLOCATE_AND_GC_LIST(MEM_ALLOCATE_AND_GC_NAME)
150 #undef MEM_ALLOCATE_AND_GC_NAME
151 #define DEF_RUNTIME_ID(name) "Runtime::" #name,
152     RUNTIME_STUB_WITH_GC_LIST(DEF_RUNTIME_ID)
153 #undef DEF_RUNTIME_ID
154     };
155     static_assert(sizeof(runtimeCallerNames) == sizeof(const char *) * ecmascript::RUNTIME_CALLER_NUMBER,
156                   "Invalid runtime caller number");
157     runtimeStat_ = vm_->GetChunk()->New<EcmaRuntimeStat>(runtimeCallerNames, ecmascript::RUNTIME_CALLER_NUMBER);
158     if (UNLIKELY(runtimeStat_ == nullptr)) {
159         LOG_FULL(FATAL) << "alloc runtimeStat_ failed";
160         UNREACHABLE();
161     }
162 }
163 
SetRuntimeStatEnable(bool flag)164 void EcmaContext::SetRuntimeStatEnable(bool flag)
165 {
166     static uint64_t start = 0;
167     if (flag) {
168         start = PandaRuntimeTimer::Now();
169         if (runtimeStat_ == nullptr) {
170             InitializeEcmaScriptRunStat();
171         }
172     } else {
173         LOG_ECMA(INFO) << "Runtime State duration:" << PandaRuntimeTimer::Now() - start << "(ns)";
174         if (runtimeStat_ != nullptr && runtimeStat_->IsRuntimeStatEnabled()) {
175             runtimeStat_->Print();
176             runtimeStat_->ResetAllCount();
177         }
178     }
179     if (runtimeStat_ != nullptr) {
180         runtimeStat_->SetRuntimeStatEnabled(flag);
181     }
182 }
183 
~EcmaContext()184 EcmaContext::~EcmaContext()
185 {
186     if (runtimeStat_ != nullptr && runtimeStat_->IsRuntimeStatEnabled()) {
187         runtimeStat_->Print();
188     }
189     for (auto n : handleStorageNodes_) {
190         delete n;
191     }
192     handleStorageNodes_.clear();
193     currentHandleStorageIndex_ = -1;
194     handleScopeCount_ = 0;
195     handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr;
196     ClearBufferData();
197     // clear c_address: c++ pointer delete
198     if (!vm_->IsBundlePack()) {
199         std::shared_ptr<JSPandaFile> jsPandaFile =
200             JSPandaFileManager::GetInstance()->FindJSPandaFile(vm_->GetAssetPath());
201         if (jsPandaFile != nullptr) {
202             jsPandaFile->DeleteParsedConstpoolVM(vm_);
203         }
204     }
205     // clear icu cache
206     ClearIcuCache();
207 
208     if (runtimeStat_ != nullptr) {
209         vm_->GetChunk()->Delete(runtimeStat_);
210         runtimeStat_ = nullptr;
211     }
212     if (optCodeProfiler_ != nullptr) {
213         delete optCodeProfiler_;
214         optCodeProfiler_ = nullptr;
215     }
216     if (typedOpProfiler_ != nullptr) {
217         delete typedOpProfiler_;
218         typedOpProfiler_ = nullptr;
219     }
220     if (moduleManager_ != nullptr) {
221         delete moduleManager_;
222         moduleManager_ = nullptr;
223     }
224     if (tsManager_ != nullptr) {
225         delete tsManager_;
226         tsManager_ = nullptr;
227     }
228     if (ptManager_ != nullptr) {
229         delete ptManager_;
230         ptManager_ = nullptr;
231     }
232     if (regExpParserCache_ != nullptr) {
233         delete regExpParserCache_;
234         regExpParserCache_ = nullptr;
235     }
236     if (aotFileManager_ != nullptr) {
237         delete aotFileManager_;
238         aotFileManager_ = nullptr;
239     }
240     if (propertiesCache_ != nullptr) {
241         delete propertiesCache_;
242         propertiesCache_ = nullptr;
243     }
244     // clear join stack
245     joinStack_.clear();
246 
247     for (auto v : stringifyCache_) {
248         v.clear();
249     }
250 }
251 
InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc,JSHandle<JSTaggedValue> & thisArg,const JSPandaFile * jsPandaFile,std::string_view entryPoint,CJSInfo * cjsInfo)252 JSTaggedValue EcmaContext::InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc, JSHandle<JSTaggedValue> &thisArg,
253                                                    const JSPandaFile *jsPandaFile, std::string_view entryPoint,
254                                                    CJSInfo* cjsInfo)
255 {
256     aotFileManager_->SetAOTMainFuncEntry(mainFunc, jsPandaFile, entryPoint);
257     return JSFunction::InvokeOptimizedEntrypoint(thread_, mainFunc, thisArg, entryPoint, cjsInfo);
258 }
259 
ExecuteAot(size_t actualNumArgs,JSTaggedType * args,const JSTaggedType * prevFp,bool needPushUndefined)260 JSTaggedValue EcmaContext::ExecuteAot(size_t actualNumArgs, JSTaggedType *args,
261                                       const JSTaggedType *prevFp, bool needPushUndefined)
262 {
263     INTERPRETER_TRACE(thread_, ExecuteAot);
264     auto entry = thread_->GetRTInterface(kungfu::RuntimeStubCSigns::ID_JSFunctionEntry);
265     // do not modify this log to INFO, this will call many times
266     LOG_ECMA(DEBUG) << "start to execute aot entry: " << (void*)entry;
267     auto res = reinterpret_cast<JSFunctionEntryType>(entry)(thread_->GetGlueAddr(),
268                                                             actualNumArgs,
269                                                             args,
270                                                             reinterpret_cast<uintptr_t>(prevFp),
271                                                             needPushUndefined);
272     return res;
273 }
274 
CommonInvokeEcmaEntrypoint(const JSPandaFile * jsPandaFile,std::string_view entryPoint,JSHandle<JSFunction> & func)275 Expected<JSTaggedValue, bool> EcmaContext::CommonInvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile,
276     std::string_view entryPoint, JSHandle<JSFunction> &func)
277 {
278     JSHandle<Method> method(thread_, func->GetMethod());
279     JSHandle<JSTaggedValue> global = GlobalEnv::Cast(globalEnv_.GetTaggedObject())->GetJSGlobalObject();
280     JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
281     CString entry = entryPoint.data();
282     JSRecordInfo recordInfo;
283     bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(entry, recordInfo);
284     if (!hasRecord) {
285         CString msg = "cannot find record '" + entry + "', please check the request path.";
286         LOG_FULL(ERROR) << msg;
287         THROW_REFERENCE_ERROR_AND_RETURN(thread_, msg.c_str(), Unexpected(false));
288     }
289     if (jsPandaFile->IsModule(recordInfo)) {
290         global = undefined;
291         CString moduleName = jsPandaFile->GetJSPandaFileDesc();
292         if (!jsPandaFile->IsBundlePack()) {
293             moduleName = entry;
294         }
295         JSHandle<SourceTextModule> module = moduleManager_->HostGetImportedModule(moduleName);
296         method->SetModule(thread_, module);
297     } else {
298         // if it is Cjs at present, the module slot of the function is not used. We borrow it to store the recordName,
299         // which can avoid the problem of larger memory caused by the new slot
300         JSHandle<EcmaString> recordName = factory_->NewFromUtf8(entry);
301         method->SetModule(thread_, recordName);
302     }
303     vm_->CheckStartCpuProfiler();
304 
305     JSTaggedValue result;
306     if (jsPandaFile->IsCjs(recordInfo)) {
307         CJSExecution(func, global, jsPandaFile, entryPoint);
308     } else {
309         if (aotFileManager_->IsLoadMain(jsPandaFile, entry)) {
310             EcmaRuntimeStatScope runtimeStatScope(vm_);
311             result = InvokeEcmaAotEntrypoint(func, global, jsPandaFile, entryPoint);
312         } else if (vm_->GetJSOptions().IsEnableForceJitCompileMain()) {
313             Jit::Compile(vm_, func);
314             EcmaRuntimeStatScope runtimeStatScope(vm_);
315             result = JSFunction::InvokeOptimizedEntrypoint(thread_, func, global, entryPoint, nullptr);
316         } else {
317             EcmaRuntimeCallInfo *info =
318                 EcmaInterpreter::NewRuntimeCallInfo(thread_, JSHandle<JSTaggedValue>(func), global, undefined, 0);
319             EcmaRuntimeStatScope runtimeStatScope(vm_);
320             result = EcmaInterpreter::Execute(info);
321         }
322     }
323     if (!thread_->HasPendingException()) {
324         job::MicroJobQueue::ExecutePendingJob(thread_, GetMicroJobQueue());
325     }
326 
327     return result;
328 }
329 
InvokeEcmaEntrypoint(const JSPandaFile * jsPandaFile,std::string_view entryPoint,bool excuteFromJob)330 Expected<JSTaggedValue, bool> EcmaContext::InvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile,
331                                                                 std::string_view entryPoint, bool excuteFromJob)
332 {
333     [[maybe_unused]] EcmaHandleScope scope(thread_);
334     JSHandle<Program> program = JSPandaFileManager::GetInstance()->GenerateProgram(vm_, jsPandaFile, entryPoint);
335     if (program.IsEmpty()) {
336         LOG_ECMA(ERROR) << "program is empty, invoke entrypoint failed";
337         return Unexpected(false);
338     }
339     // for debugger
340     vm_->GetJsDebuggerManager()->GetNotificationManager()->LoadModuleEvent(
341         jsPandaFile->GetJSPandaFileDesc(), entryPoint);
342 
343     JSHandle<JSFunction> func(thread_, program->GetMainFunction());
344     Expected<JSTaggedValue, bool> result = CommonInvokeEcmaEntrypoint(jsPandaFile, entryPoint, func);
345 
346     // print exception information
347     if (!excuteFromJob && thread_->HasPendingException()) {
348         HandleUncaughtException(thread_->GetException());
349     }
350     return result;
351 }
352 
InvokeEcmaEntrypointForHotReload(const JSPandaFile * jsPandaFile,std::string_view entryPoint,bool excuteFromJob)353 Expected<JSTaggedValue, bool> EcmaContext::InvokeEcmaEntrypointForHotReload(
354     const JSPandaFile *jsPandaFile, std::string_view entryPoint, bool excuteFromJob)
355 {
356     [[maybe_unused]] EcmaHandleScope scope(thread_);
357     JSHandle<Program> program = JSPandaFileManager::GetInstance()->GenerateProgram(vm_, jsPandaFile, entryPoint);
358 
359     JSHandle<JSFunction> func(thread_, program->GetMainFunction());
360     Expected<JSTaggedValue, bool> result = CommonInvokeEcmaEntrypoint(jsPandaFile, entryPoint, func);
361 
362     JSHandle<JSTaggedValue> finalModuleRecord(thread_, func->GetModule());
363     // avoid GC problems.
364     GlobalHandleCollection gloalHandleCollection(thread_);
365     JSHandle<JSTaggedValue> moduleRecordHandle =
366         gloalHandleCollection.NewHandle<JSTaggedValue>(finalModuleRecord->GetRawData());
367     CString recordName = entryPoint.data();
368     AddPatchModule(recordName, moduleRecordHandle);
369 
370     // print exception information
371     if (!excuteFromJob && thread_->HasPendingException() &&
372         Method::Cast(func->GetMethod())->GetMethodName() != JSPandaFile::PATCH_FUNCTION_NAME_0) {
373         HandleUncaughtException(thread_->GetException());
374     }
375     return result;
376 }
377 
CJSExecution(JSHandle<JSFunction> & func,JSHandle<JSTaggedValue> & thisArg,const JSPandaFile * jsPandaFile,std::string_view entryPoint)378 void EcmaContext::CJSExecution(JSHandle<JSFunction> &func, JSHandle<JSTaggedValue> &thisArg,
379                                const JSPandaFile *jsPandaFile, std::string_view entryPoint)
380 {
381     // create "module", "exports", "require", "filename", "dirname"
382     JSHandle<CjsModule> module = factory_->NewCjsModule();
383     JSHandle<JSTaggedValue> require = GetGlobalEnv()->GetCjsRequireFunction();
384     JSHandle<CjsExports> exports = factory_->NewCjsExports();
385     JSMutableHandle<JSTaggedValue> filename(thread_, JSTaggedValue::Undefined());
386     JSMutableHandle<JSTaggedValue> dirname(thread_, JSTaggedValue::Undefined());
387     if (jsPandaFile->IsBundlePack()) {
388         ModulePathHelper::ResolveCurrentPath(thread_, dirname, filename, jsPandaFile);
389     } else {
390         filename.Update(func->GetModule());
391         ASSERT(filename->IsString());
392         CString fullName = ConvertToString(filename.GetTaggedValue());
393         dirname.Update(PathHelper::ResolveDirPath(thread_, fullName));
394     }
395     CJSInfo cjsInfo(module, require, exports, filename, dirname);
396     RequireManager::InitializeCommonJS(thread_, cjsInfo);
397     if (aotFileManager_->IsLoadMain(jsPandaFile, entryPoint.data())) {
398         EcmaRuntimeStatScope runtimeStateScope(vm_);
399         isAotEntry_ = true;
400         InvokeEcmaAotEntrypoint(func, thisArg, jsPandaFile, entryPoint, &cjsInfo);
401     } else {
402         // Execute main function
403         JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
404         EcmaRuntimeCallInfo *info =
405             EcmaInterpreter::NewRuntimeCallInfo(thread_,
406                                                 JSHandle<JSTaggedValue>(func),
407                                                 thisArg, undefined, 5); // 5 : argument numbers
408         RETURN_IF_ABRUPT_COMPLETION(thread_);
409         if (info == nullptr) {
410             LOG_ECMA(ERROR) << "CJSExecution Stack overflow!";
411             return;
412         }
413         info->SetCallArg(cjsInfo.exportsHdl.GetTaggedValue(),
414             cjsInfo.requireHdl.GetTaggedValue(),
415             cjsInfo.moduleHdl.GetTaggedValue(),
416             cjsInfo.filenameHdl.GetTaggedValue(),
417             cjsInfo.dirnameHdl.GetTaggedValue());
418         EcmaRuntimeStatScope runtimeStatScope(vm_);
419         EcmaInterpreter::Execute(info);
420     }
421     if (!thread_->HasPendingException()) {
422         job::MicroJobQueue::ExecutePendingJob(thread_, thread_->GetCurrentEcmaContext()->GetMicroJobQueue());
423     }
424 
425     if (!thread_->HasPendingException()) {
426         // Collecting module.exports : exports ---> module.exports --->Module._cache
427         RequireManager::CollectExecutedExp(thread_, cjsInfo);
428     }
429 }
430 
HasCachedConstpool(const JSPandaFile * jsPandaFile) const431 bool EcmaContext::HasCachedConstpool(const JSPandaFile *jsPandaFile) const
432 {
433     return cachedConstpools_.find(jsPandaFile) != cachedConstpools_.end();
434 }
435 
FindConstpool(const JSPandaFile * jsPandaFile,int32_t index)436 JSTaggedValue EcmaContext::FindConstpool(const JSPandaFile *jsPandaFile, int32_t index)
437 {
438     auto iter = cachedConstpools_.find(jsPandaFile);
439     if (iter == cachedConstpools_.end()) {
440         return JSTaggedValue::Hole();
441     }
442     auto constpoolIter = iter->second.find(index);
443     if (constpoolIter == iter->second.end()) {
444         return JSTaggedValue::Hole();
445     }
446     return constpoolIter->second;
447 }
448 
FindConstpools(const JSPandaFile * jsPandaFile)449 std::optional<std::reference_wrapper<CMap<int32_t, JSTaggedValue>>> EcmaContext::FindConstpools(
450     const JSPandaFile *jsPandaFile)
451 {
452     auto iter = cachedConstpools_.find(jsPandaFile);
453     if (iter == cachedConstpools_.end()) {
454         return std::nullopt;
455     }
456     return iter->second;
457 }
458 
459 // For new version instruction.
FindConstpool(const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)460 JSTaggedValue EcmaContext::FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id)
461 {
462     panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
463     int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
464     return FindConstpool(jsPandaFile, index);
465 }
466 
FindConstpoolWithAOT(const JSPandaFile * jsPandaFile,int32_t index)467 JSTaggedValue EcmaContext::FindConstpoolWithAOT(const JSPandaFile *jsPandaFile, int32_t index)
468 {
469     JSTaggedValue constpool = FindConstpool(jsPandaFile, index);
470     // In the taskpool thread, there is a case where the Function object is serialized before InitForCurrentThread.
471     // A constpool is created when a Function is serialized. Slowpath, the default deserialized constpool,
472     // string is non-lazy load mode. A hole is returned if you access the constpool of the serialized Function
473     if (constpool.IsHole() && ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
474         bool result = GetAOTFileManager()->LoadAiFile(jsPandaFile);
475         if (result) {
476             constpool = FindConstpool(jsPandaFile, index);
477         }
478     }
479     return constpool;
480 }
481 
FindOrCreateConstPool(const JSPandaFile * jsPandaFile,panda_file::File::EntityId id)482 JSHandle<ConstantPool> EcmaContext::FindOrCreateConstPool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id)
483 {
484     panda_file::IndexAccessor indexAccessor(*jsPandaFile->GetPandaFile(), id);
485     int32_t index = static_cast<int32_t>(indexAccessor.GetHeaderIndex());
486     JSTaggedValue constpool = FindConstpoolWithAOT(jsPandaFile, index);
487     if (constpool.IsHole()) {
488         JSHandle<ConstantPool> newConstpool = ConstantPool::CreateConstPool(vm_, jsPandaFile, id);
489         AddConstpool(jsPandaFile, newConstpool.GetTaggedValue(), index);
490         return newConstpool;
491     }
492     return JSHandle<ConstantPool>(thread_, constpool);
493 }
494 
CreateAllConstpool(const JSPandaFile * jsPandaFile)495 void EcmaContext::CreateAllConstpool(const JSPandaFile *jsPandaFile)
496 {
497     auto headers = jsPandaFile->GetPandaFile()->GetIndexHeaders();
498     uint32_t index = 0;
499     for (const auto &header : headers) {
500         auto constpoolSize = header.method_idx_size;
501         JSHandle<ConstantPool> constpool = factory_->NewConstantPool(constpoolSize);
502         constpool->SetJSPandaFile(jsPandaFile);
503         constpool->SetIndexHeader(&header);
504         AddConstpool(jsPandaFile, constpool.GetTaggedValue(), index++);
505     }
506 }
507 
AddConstpool(const JSPandaFile * jsPandaFile,JSTaggedValue constpool,int32_t index)508 void EcmaContext::AddConstpool(const JSPandaFile *jsPandaFile, JSTaggedValue constpool, int32_t index)
509 {
510     ASSERT(constpool.IsConstantPool());
511     if (cachedConstpools_.find(jsPandaFile) == cachedConstpools_.end()) {
512         cachedConstpools_[jsPandaFile] = CMap<int32_t, JSTaggedValue>();
513     }
514     auto &constpoolMap = cachedConstpools_[jsPandaFile];
515     ASSERT(constpoolMap.find(index) == constpoolMap.end());
516     constpoolMap.insert({index, constpool});
517 }
518 
GetAndClearEcmaUncaughtException() const519 JSHandle<JSTaggedValue> EcmaContext::GetAndClearEcmaUncaughtException() const
520 {
521     JSHandle<JSTaggedValue> exceptionHandle = GetEcmaUncaughtException();
522     thread_->ClearException();  // clear for ohos app
523     return exceptionHandle;
524 }
525 
ProcessNativeDelete(const WeakRootVisitor & visitor)526 void EcmaContext::ProcessNativeDelete(const WeakRootVisitor &visitor)
527 {
528     auto iterator = cachedConstpools_.begin();
529     while (iterator != cachedConstpools_.end()) {
530         auto &constpools = iterator->second;
531         auto constpoolIter = constpools.begin();
532         while (constpoolIter != constpools.end()) {
533             JSTaggedValue constpoolVal = constpoolIter->second;
534             if (constpoolVal.IsHeapObject()) {
535                 TaggedObject *obj = constpoolVal.GetTaggedObject();
536                 auto fwd = visitor(obj);
537                 if (fwd == nullptr) {
538                     constpoolIter = constpools.erase(constpoolIter);
539                     continue;
540                 }
541             }
542             ++constpoolIter;
543         }
544         if (constpools.size() == 0) {
545             LOG_ECMA(INFO) << "remove js pandafile by gc, file:" << iterator->first->GetJSPandaFileDesc();
546             RelocateConstantString(iterator->first);
547             JSPandaFileManager::GetInstance()->RemoveJSPandaFileVm(vm_, iterator->first);
548             iterator = cachedConstpools_.erase(iterator);
549         } else {
550             ++iterator;
551         }
552     }
553 }
554 
ProcessReferences(const WeakRootVisitor & visitor)555 void EcmaContext::ProcessReferences(const WeakRootVisitor &visitor)
556 {
557     auto iterator = cachedConstpools_.begin();
558     while (iterator != cachedConstpools_.end()) {
559         auto &constpools = iterator->second;
560         auto constpoolIter = constpools.begin();
561         while (constpoolIter != constpools.end()) {
562             JSTaggedValue constpoolVal = constpoolIter->second;
563             if (constpoolVal.IsHeapObject()) {
564                 TaggedObject *obj = constpoolVal.GetTaggedObject();
565                 auto fwd = visitor(obj);
566                 if (fwd == nullptr) {
567                     constpoolIter = constpools.erase(constpoolIter);
568                     continue;
569                 } else if (fwd != obj) {
570                     constpoolIter->second = JSTaggedValue(fwd);
571                 }
572             }
573             ++constpoolIter;
574         }
575         if (constpools.size() == 0) {
576             LOG_ECMA(INFO) << "remove js pandafile by gc, file:" << iterator->first->GetJSPandaFileDesc();
577             RelocateConstantString(iterator->first);
578             JSPandaFileManager::GetInstance()->RemoveJSPandaFileVm(vm_, iterator->first);
579             iterator = cachedConstpools_.erase(iterator);
580         } else {
581             ++iterator;
582         }
583     }
584 }
585 
RelocateConstantString(const JSPandaFile * jsPandaFile)586 void EcmaContext::RelocateConstantString(const JSPandaFile *jsPandaFile)
587 {
588     if (!jsPandaFile->IsFirstMergedAbc()) {
589         return;
590     }
591     vm_->GetEcmaStringTable()->RelocateConstantData(jsPandaFile);
592 }
593 
GetEcmaUncaughtException() const594 JSHandle<JSTaggedValue> EcmaContext::GetEcmaUncaughtException() const
595 {
596     if (!thread_->HasPendingException()) {
597         return JSHandle<JSTaggedValue>();
598     }
599     JSHandle<JSTaggedValue> exceptionHandle(thread_, thread_->GetException());
600     return exceptionHandle;
601 }
602 
EnableUserUncaughtErrorHandler()603 void EcmaContext::EnableUserUncaughtErrorHandler()
604 {
605     isUncaughtExceptionRegistered_ = true;
606 }
607 
HandleUncaughtException(JSTaggedValue exception)608 void EcmaContext::HandleUncaughtException(JSTaggedValue exception)
609 {
610     if (isUncaughtExceptionRegistered_) {
611         return;
612     }
613     [[maybe_unused]] EcmaHandleScope handleScope(thread_);
614     JSHandle<JSTaggedValue> exceptionHandle(thread_, exception);
615     // if caught exceptionHandle type is JSError
616     thread_->ClearException();
617     if (exceptionHandle->IsJSError()) {
618         PrintJSErrorInfo(thread_, exceptionHandle);
619         return;
620     }
621     JSHandle<EcmaString> result = JSTaggedValue::ToString(thread_, exceptionHandle);
622     CString string = ConvertToString(*result);
623     LOG_NO_TAG(ERROR) << string;
624 }
625 
626 // static
PrintJSErrorInfo(JSThread * thread,const JSHandle<JSTaggedValue> & exceptionInfo)627 void EcmaContext::PrintJSErrorInfo(JSThread *thread, const JSHandle<JSTaggedValue> &exceptionInfo)
628 {
629     JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
630     JSHandle<JSTaggedValue> nameValue = JSObject::GetProperty(thread, exceptionInfo, nameKey).GetValue();
631     JSHandle<EcmaString> name = JSTaggedValue::ToString(thread, nameValue);
632     // JSTaggedValue::ToString may cause exception. In this case, do not return, use "<error>" instead.
633     if (thread->HasPendingException()) {
634         thread->ClearException();
635         name = thread->GetEcmaVM()->GetFactory()->NewFromStdString("<error>");
636     }
637     JSHandle<JSTaggedValue> msgKey = thread->GlobalConstants()->GetHandledMessageString();
638     JSHandle<JSTaggedValue> msgValue = JSObject::GetProperty(thread, exceptionInfo, msgKey).GetValue();
639     JSHandle<EcmaString> msg = JSTaggedValue::ToString(thread, msgValue);
640     // JSTaggedValue::ToString may cause exception. In this case, do not return, use "<error>" instead.
641     if (thread->HasPendingException()) {
642         thread->ClearException();
643         msg = thread->GetEcmaVM()->GetFactory()->NewFromStdString("<error>");
644     }
645     JSHandle<JSTaggedValue> stackKey = thread->GlobalConstants()->GetHandledStackString();
646     JSHandle<JSTaggedValue> stackValue = JSObject::GetProperty(thread, exceptionInfo, stackKey).GetValue();
647     JSHandle<EcmaString> stack = JSTaggedValue::ToString(thread, stackValue);
648     // JSTaggedValue::ToString may cause exception. In this case, do not return, use "<error>" instead.
649     if (thread->HasPendingException()) {
650         thread->ClearException();
651         stack = thread->GetEcmaVM()->GetFactory()->NewFromStdString("<error>");
652     }
653 
654     CString nameBuffer = ConvertToString(*name);
655     CString msgBuffer = ConvertToString(*msg);
656     CString stackBuffer = ConvertToString(*stack);
657     LOG_NO_TAG(ERROR) << panda::ecmascript::previewerTag << nameBuffer << ": " << msgBuffer << "\n"
658                       << (panda::ecmascript::previewerTag.empty()
659                               ? stackBuffer
660                               : std::regex_replace(stackBuffer, std::regex(".+(\n|$)"),
661                                                    panda::ecmascript::previewerTag + "$0"));
662 }
663 
HasPendingJob()664 bool EcmaContext::HasPendingJob()
665 {
666     if (UNLIKELY(thread_->HasTerminated())) {
667         return false;
668     }
669     return job::MicroJobQueue::HasPendingJob(thread_, GetMicroJobQueue());
670 }
671 
ExecutePromisePendingJob()672 bool EcmaContext::ExecutePromisePendingJob()
673 {
674     if (isProcessingPendingJob_) {
675         LOG_ECMA(DEBUG) << "EcmaVM::ExecutePromisePendingJob can not reentrant";
676         return false;
677     }
678     if (!thread_->HasPendingException()) {
679         isProcessingPendingJob_ = true;
680         job::MicroJobQueue::ExecutePendingJob(thread_, GetMicroJobQueue());
681         isProcessingPendingJob_ = false;
682         return true;
683     }
684     return false;
685 }
686 
ClearBufferData()687 void EcmaContext::ClearBufferData()
688 {
689     auto iter = cachedConstpools_.begin();
690     while (iter != cachedConstpools_.end()) {
691         LOG_ECMA(INFO) << "remove js pandafile by vm destruct, file:" << iter->first->GetJSPandaFileDesc();
692         JSPandaFileManager::GetInstance()->RemoveJSPandaFileVm(vm_, iter->first);
693         iter++;
694     }
695     cachedConstpools_.clear();
696 }
697 
SetGlobalEnv(GlobalEnv * global)698 void EcmaContext::SetGlobalEnv(GlobalEnv *global)
699 {
700     ASSERT(global != nullptr);
701     globalEnv_ = JSTaggedValue(global);
702 }
703 
SetMicroJobQueue(job::MicroJobQueue * queue)704 void EcmaContext::SetMicroJobQueue(job::MicroJobQueue *queue)
705 {
706     ASSERT(queue != nullptr);
707     microJobQueue_ = JSTaggedValue(queue);
708 }
709 
GetGlobalEnv() const710 JSHandle<GlobalEnv> EcmaContext::GetGlobalEnv() const
711 {
712     return JSHandle<GlobalEnv>(reinterpret_cast<uintptr_t>(&globalEnv_));
713 }
714 
GetMicroJobQueue() const715 JSHandle<job::MicroJobQueue> EcmaContext::GetMicroJobQueue() const
716 {
717     return JSHandle<job::MicroJobQueue>(reinterpret_cast<uintptr_t>(&microJobQueue_));
718 }
719 
MountContext(JSThread * thread)720 void EcmaContext::MountContext(JSThread *thread)
721 {
722     EcmaContext *context = EcmaContext::CreateAndInitialize(thread);
723     thread->SwitchCurrentContext(context);
724 }
725 
UnmountContext(JSThread * thread)726 void EcmaContext::UnmountContext(JSThread *thread)
727 {
728     EcmaContext *context = thread->GetCurrentEcmaContext();
729     thread->PopContext();
730     Destroy(context);
731 }
732 
CreateAndInitialize(JSThread * thread)733 EcmaContext *EcmaContext::CreateAndInitialize(JSThread *thread)
734 {
735     EcmaContext *context = EcmaContext::Create(thread);
736     thread->PushContext(context);
737     context->Initialize();
738     return context;
739 }
740 
CheckAndDestroy(JSThread * thread,EcmaContext * context)741 void EcmaContext::CheckAndDestroy(JSThread *thread, EcmaContext *context)
742 {
743     if (thread->EraseContext(context)) {
744         Destroy(context);
745         return;
746     }
747     LOG_ECMA(FATAL) << "CheckAndDestroy a nonexistent context.";
748 }
749 
SetupRegExpResultCache()750 void EcmaContext::SetupRegExpResultCache()
751 {
752     regexpCache_ = builtins::RegExpExecResultCache::CreateCacheTable(thread_);
753 }
754 
SetupRegExpGlobalResult()755 void EcmaContext::SetupRegExpGlobalResult()
756 {
757     regexpGlobal_ = builtins::RegExpGlobalResult::CreateGlobalResultTable(thread_);
758 }
759 
SetupNumberToStringResultCache()760 void EcmaContext::SetupNumberToStringResultCache()
761 {
762     numberToStringResultCache_ = builtins::NumberToStringResultCache::CreateCacheTable(thread_);
763 }
764 
SetupStringSplitResultCache()765 void EcmaContext::SetupStringSplitResultCache()
766 {
767     stringSplitResultCache_ = builtins::StringSplitResultCache::CreateCacheTable(thread_);
768 }
769 
SetupStringToListResultCache()770 void EcmaContext::SetupStringToListResultCache()
771 {
772     stringToListResultCache_ = builtins::StringToListResultCache::CreateCacheTable(thread_);
773 }
774 
Iterate(const RootVisitor & v,const RootRangeVisitor & rv)775 void EcmaContext::Iterate(const RootVisitor &v, const RootRangeVisitor &rv)
776 {
777     // visit global Constant
778     globalConst_.VisitRangeSlot(rv);
779 
780     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&globalEnv_)));
781     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&regexpCache_)));
782     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&regexpGlobal_)));
783     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&numberToStringResultCache_)));
784     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&stringSplitResultCache_)));
785     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&stringToListResultCache_)));
786     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&microJobQueue_)));
787     v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&pointerToIndexDictionary_)));
788 
789     if (moduleManager_) {
790         moduleManager_->Iterate(v);
791     }
792     if (tsManager_) {
793         tsManager_->Iterate(v);
794     }
795     if (ptManager_) {
796         ptManager_->Iterate(v);
797     }
798     if (aotFileManager_) {
799         aotFileManager_->Iterate(v);
800     }
801     if (propertiesCache_ != nullptr) {
802         propertiesCache_->Clear();
803     }
804     if (!vm_->GetJSOptions().EnableGlobalLeakCheck() && currentHandleStorageIndex_ != -1) {
805         // IterateHandle when disableGlobalLeakCheck.
806         int32_t nid = currentHandleStorageIndex_;
807         for (int32_t i = 0; i <= nid; ++i) {
808             auto node = handleStorageNodes_.at(i);
809             auto start = node->data();
810             auto end = (i != nid) ? &(node->data()[NODE_BLOCK_SIZE]) : handleScopeStorageNext_;
811             rv(ecmascript::Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(start)), ObjectSlot(ToUintPtr(end)));
812         }
813     }
814 
815     if (!joinStack_.empty()) {
816         rv(Root::ROOT_VM, ObjectSlot(ToUintPtr(&joinStack_.front())),
817             ObjectSlot(ToUintPtr(&joinStack_.back()) + JSTaggedValue::TaggedTypeSize()));
818     }
819 }
820 
IterateHandle(const RootRangeVisitor & rangeVisitor)821 size_t EcmaContext::IterateHandle(const RootRangeVisitor &rangeVisitor)
822 {
823     // EnableGlobalLeakCheck.
824     size_t handleCount = 0;
825     if (currentHandleStorageIndex_ != -1) {
826         int32_t nid = currentHandleStorageIndex_;
827         for (int32_t i = 0; i <= nid; ++i) {
828             auto node = handleStorageNodes_.at(i);
829             auto start = node->data();
830             auto end = (i != nid) ? &(node->data()[NODE_BLOCK_SIZE]) : handleScopeStorageNext_;
831             rangeVisitor(ecmascript::Root::ROOT_HANDLE, ObjectSlot(ToUintPtr(start)), ObjectSlot(ToUintPtr(end)));
832             handleCount += (ToUintPtr(end) - ToUintPtr(start)) / sizeof(JSTaggedType);
833         }
834     }
835     return handleCount;
836 }
837 
ExpandHandleStorage()838 uintptr_t *EcmaContext::ExpandHandleStorage()
839 {
840     uintptr_t *result = nullptr;
841     int32_t lastIndex = static_cast<int32_t>(handleStorageNodes_.size() - 1);
842     if (currentHandleStorageIndex_ == lastIndex) {
843         auto n = new std::array<JSTaggedType, NODE_BLOCK_SIZE>();
844         handleStorageNodes_.push_back(n);
845         currentHandleStorageIndex_++;
846         result = reinterpret_cast<uintptr_t *>(&n->data()[0]);
847         handleScopeStorageEnd_ = &n->data()[NODE_BLOCK_SIZE];
848     } else {
849         currentHandleStorageIndex_++;
850         auto lastNode = handleStorageNodes_[currentHandleStorageIndex_];
851         result = reinterpret_cast<uintptr_t *>(&lastNode->data()[0]);
852         handleScopeStorageEnd_ = &lastNode->data()[NODE_BLOCK_SIZE];
853     }
854 
855     return result;
856 }
857 
ShrinkHandleStorage(int prevIndex)858 void EcmaContext::ShrinkHandleStorage(int prevIndex)
859 {
860     currentHandleStorageIndex_ = prevIndex;
861     int32_t lastIndex = static_cast<int32_t>(handleStorageNodes_.size() - 1);
862 #if ECMASCRIPT_ENABLE_ZAP_MEM
863     uintptr_t size = ToUintPtr(handleScopeStorageEnd_) - ToUintPtr(handleScopeStorageNext_);
864     if (currentHandleStorageIndex_ != -1) {
865         if (memset_s(handleScopeStorageNext_, size, 0, size) != EOK) {
866             LOG_FULL(FATAL) << "memset_s failed";
867             UNREACHABLE();
868         }
869     }
870     for (int32_t i = currentHandleStorageIndex_ + 1; i < lastIndex; i++) {
871         if (memset_s(handleStorageNodes_[i],
872                      NODE_BLOCK_SIZE * sizeof(JSTaggedType), 0,
873                      NODE_BLOCK_SIZE * sizeof(JSTaggedType)) !=
874                      EOK) {
875             LOG_FULL(FATAL) << "memset_s failed";
876             UNREACHABLE();
877         }
878     }
879 #endif
880 
881     if (lastIndex > MIN_HANDLE_STORAGE_SIZE && currentHandleStorageIndex_ < MIN_HANDLE_STORAGE_SIZE) {
882         for (int i = MIN_HANDLE_STORAGE_SIZE; i < lastIndex; i++) {
883             auto node = handleStorageNodes_.back();
884             delete node;
885             handleStorageNodes_.pop_back();
886         }
887     }
888 }
889 
LoadStubFile()890 void EcmaContext::LoadStubFile()
891 {
892     std::string stubFile = vm_->GetJSOptions().GetStubFile();
893     aotFileManager_->LoadStubFile(stubFile);
894 }
895 
LoadAOTFiles(const std::string & aotFileName)896 bool EcmaContext::LoadAOTFiles(const std::string& aotFileName)
897 {
898     std::string anFile = aotFileName + AOTFileManager::FILE_EXTENSION_AN;
899     if (!aotFileManager_->LoadAnFile(anFile)) {
900         LOG_ECMA(WARN) << "Load " << anFile << " failed. Destroy aot data and rollback to interpreter";
901         ecmascript::AnFileDataManager::GetInstance()->SafeDestroyAnData(anFile);
902         return false;
903     }
904 
905     std::string aiFile = aotFileName + AOTFileManager::FILE_EXTENSION_AI;
906     if (!aotFileManager_->LoadAiFile(aiFile)) {
907         LOG_ECMA(WARN) << "Load " << aiFile << " failed. Destroy aot data and rollback to interpreter";
908         ecmascript::AnFileDataManager::GetInstance()->SafeDestroyAnData(anFile);
909         return false;
910     }
911     return true;
912 }
913 
PrintOptStat()914 void EcmaContext::PrintOptStat()
915 {
916     if (optCodeProfiler_ != nullptr) {
917         optCodeProfiler_->PrintAndReset();
918     }
919 }
920 
DumpAOTInfo() const921 void EcmaContext::DumpAOTInfo() const
922 {
923     aotFileManager_->DumpAOTInfo();
924 }
925 
JoinStackPushFastPath(JSHandle<JSTaggedValue> receiver)926 bool EcmaContext::JoinStackPushFastPath(JSHandle<JSTaggedValue> receiver)
927 {
928     if (JSTaggedValue::SameValue(joinStack_[0], JSTaggedValue::Hole())) {
929         joinStack_[0] = receiver.GetTaggedValue();
930         return true;
931     }
932     return JoinStackPush(receiver);
933 }
934 
JoinStackPush(JSHandle<JSTaggedValue> receiver)935 bool EcmaContext::JoinStackPush(JSHandle<JSTaggedValue> receiver)
936 {
937     uint32_t capacity = joinStack_.size();
938     JSTaggedValue receiverValue = receiver.GetTaggedValue();
939     for (size_t i = 0; i < capacity; ++i) {
940         if (JSTaggedValue::SameValue(joinStack_[i], JSTaggedValue::Hole())) {
941             joinStack_[i] = receiverValue;
942             return true;
943         }
944         if (JSTaggedValue::SameValue(joinStack_[i], receiverValue)) {
945             return false;
946         }
947     }
948     joinStack_.emplace_back(receiverValue);
949     return true;
950 }
951 
JoinStackPopFastPath(JSHandle<JSTaggedValue> receiver)952 void EcmaContext::JoinStackPopFastPath(JSHandle<JSTaggedValue> receiver)
953 {
954     uint32_t length = joinStack_.size();
955     if (JSTaggedValue::SameValue(joinStack_[0], receiver.GetTaggedValue()) && length == MIN_JOIN_STACK_SIZE) {
956         joinStack_[0] = JSTaggedValue::Hole();
957     } else {
958         JoinStackPop(receiver);
959     }
960 }
961 
JoinStackPop(JSHandle<JSTaggedValue> receiver)962 void EcmaContext::JoinStackPop(JSHandle<JSTaggedValue> receiver)
963 {
964     uint32_t length = joinStack_.size();
965     for (size_t i = 0; i < length; ++i) {
966         if (JSTaggedValue::SameValue(joinStack_[i], receiver.GetTaggedValue())) {
967             if (i == 0 && length > MIN_JOIN_STACK_SIZE) {
968                 joinStack_ = {JSTaggedValue::Hole(), JSTaggedValue::Hole()};
969                 break;
970             } else {
971                 joinStack_[i] = JSTaggedValue::Hole();
972                 break;
973             }
974         }
975     }
976 }
977 
CalCallSiteInfo(uintptr_t retAddr) const978 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> EcmaContext::CalCallSiteInfo(
979     uintptr_t retAddr) const
980 {
981     auto loader = GetAOTFileManager();
982     auto callSiteInfo = loader->CalCallSiteInfo(retAddr);
983     if (std::get<1>(callSiteInfo) != nullptr) {
984         return callSiteInfo;
985     }
986     // try get jit code
987     callSiteInfo = thread_->GetEcmaVM()->GetHeap()->CalCallSiteInfo(retAddr);
988     return callSiteInfo;
989 }
990 }  // namespace panda::ecmascript
991