• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_ECMA_VM_H
17 #define ECMASCRIPT_ECMA_VM_H
18 
19 #include <mutex>
20 
21 #include "ecmascript/base/config.h"
22 #include "ecmascript/builtins/builtins_method_index.h"
23 #include "ecmascript/js_handle.h"
24 #include "ecmascript/js_runtime_options.h"
25 #include "ecmascript/js_thread.h"
26 #include "ecmascript/mem/c_containers.h"
27 #include "ecmascript/mem/c_string.h"
28 #include "ecmascript/napi/include/jsnapi.h"
29 #include "ecmascript/taskpool/taskpool.h"
30 #include "ecmascript/waiter_list.h"
31 
32 namespace panda {
33 class JSNApi;
34 namespace panda_file {
35 class File;
36 }  // namespace panda_file
37 
38 namespace ecmascript {
39 class GlobalEnv;
40 class ObjectFactory;
41 class RegExpParserCache;
42 class EcmaRuntimeStat;
43 class Heap;
44 class HeapTracker;
45 class JSNativePointer;
46 class Program;
47 class GCStats;
48 class CpuProfiler;
49 class RegExpExecResultCache;
50 class JSPromise;
51 enum class PromiseRejectionEvent : uint8_t;
52 class JSPandaFileManager;
53 class JSPandaFile;
54 class EcmaStringTable;
55 class SnapshotEnv;
56 class SnapshotSerialize;
57 class SnapshotProcessor;
58 class PGOProfiler;
59 #if !WIN_OR_MAC_OR_IOS_PLATFORM
60 class HeapProfilerInterface;
61 #endif
62 namespace job {
63 class MicroJobQueue;
64 }  // namespace job
65 
66 namespace tooling {
67 class JsDebuggerManager;
68 }  // namespace tooling
69 
70 template<typename T>
71 class JSHandle;
72 class JSArrayBuffer;
73 class JSFunction;
74 class Program;
75 class TSManager;
76 class AOTFileManager;
77 class ModuleManager;
78 class CjsModule;
79 class CjsExports;
80 class CjsRequire;
81 class CjsModuleCache;
82 class SlowRuntimeStub;
83 class RequireManager;
84 struct CJSInfo;
85 class QuickFixManager;
86 class ConstantPool;
87 class OptCodeProfiler;
88 
89 enum class IcuFormatterType {
90     SimpleDateFormatDefault,
91     SimpleDateFormatDate,
92     SimpleDateFormatTime,
93     NumberFormatter,
94     Collator
95 };
96 using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
97                                              const JSHandle<JSPromise> promise,
98                                              const JSHandle<JSTaggedValue> reason,
99                                              PromiseRejectionEvent operation,
100                                              void* data);
101 using PromiseRejectCallback = void (*)(void* info);
102 
103 using NativePtrGetter = void* (*)(void* info);
104 
105 using ResolvePathCallback = std::function<std::string(std::string dirPath, std::string requestPath)>;
106 using ResolveBufferCallback = std::function<std::vector<uint8_t>(std::string dirPath, std::string requestPath)>;
107 using IcuDeleteEntry = void(*)(void *pointer, void *data);
108 
109 class EcmaVM {
110 public:
111     static EcmaVM *Create(const JSRuntimeOptions &options, EcmaParamConfiguration &config);
112 
113     static bool Destroy(EcmaVM *vm);
114 
115     explicit EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config);
116 
117     EcmaVM();
118 
119     ~EcmaVM();
120 
SetLoop(void * loop)121     void SetLoop(void *loop)
122     {
123         loop_ = loop;
124     }
125 
GetLoop()126     void *GetLoop() const
127     {
128         return loop_;
129     }
130 
IsInitialized()131     bool IsInitialized() const
132     {
133         return initialized_;
134     }
135 
IsGlobalConstInitialized()136     bool IsGlobalConstInitialized() const
137     {
138         return globalConstInitialized_;
139     }
140 
GetFactory()141     ObjectFactory *GetFactory() const
142     {
143         return factory_;
144     }
145 
146     void ResetPGOProfiler();
147 
148     bool IsEnablePGOProfiler() const;
149 
150     bool Initialize();
151 
GetEcmaGCStats()152     GCStats *GetEcmaGCStats() const
153     {
154         return gcStats_;
155     }
156 
GetAssociatedJSThread()157     JSThread *GetAssociatedJSThread() const
158     {
159         return thread_;
160     }
161 
GetJSOptions()162     JSRuntimeOptions &GetJSOptions()
163     {
164         return options_;
165     }
166 
GetEcmaParamConfiguration()167     const EcmaParamConfiguration &GetEcmaParamConfiguration() const
168     {
169         return ecmaParamConfiguration_;
170     }
171 
172     JSHandle<GlobalEnv> GetGlobalEnv() const;
173 
174     JSHandle<job::MicroJobQueue> GetMicroJobQueue() const;
175 
176     bool ExecutePromisePendingJob();
177 
ConstCast(const EcmaVM * vm)178     static EcmaVM *ConstCast(const EcmaVM *vm)
179     {
180         return const_cast<EcmaVM *>(vm);
181     }
182 
GetRegExpParserCache()183     RegExpParserCache *GetRegExpParserCache() const
184     {
185         ASSERT(regExpParserCache_ != nullptr);
186         return regExpParserCache_;
187     }
188 
GetEcmaStringTable()189     EcmaStringTable *GetEcmaStringTable() const
190     {
191         ASSERT(stringTable_ != nullptr);
192         return stringTable_;
193     }
194 
CheckThread()195     void CheckThread() const
196     {
197         // Exclude GC thread
198         if (thread_ == nullptr) {
199             LOG_FULL(FATAL) << "Fatal: ecma_vm has been destructed! vm address is: " << this;
200         }
201         if (!Taskpool::GetCurrentTaskpool()->IsInThreadPool(std::this_thread::get_id()) &&
202             thread_->GetThreadId() != JSThread::GetCurrentThreadId()) {
203                 LOG_FULL(FATAL) << "Fatal: ecma_vm cannot run in multi-thread!"
204                                     << " thread:" << thread_->GetThreadId()
205                                     << " currentThread:" << JSThread::GetCurrentThreadId();
206         }
207     }
208 
GetJSThread()209     ARK_INLINE JSThread *GetJSThread() const
210     {
211         if (options_.EnableThreadCheck()) {
212             CheckThread();
213         }
214         return thread_;
215     }
216 
ICEnabled()217     bool ICEnabled() const
218     {
219         return icEnabled_;
220     }
221 
222     void PushToNativePointerList(JSNativePointer *array);
223     void RemoveFromNativePointerList(JSNativePointer *array);
224 
225     JSHandle<ecmascript::JSTaggedValue> GetAndClearEcmaUncaughtException() const;
226     JSHandle<ecmascript::JSTaggedValue> GetEcmaUncaughtException() const;
227     void EnableUserUncaughtErrorHandler();
228 
GetRuntimeStat()229     EcmaRuntimeStat *GetRuntimeStat() const
230     {
231         return runtimeStat_;
232     }
233 
234     void SetRuntimeStatEnable(bool flag);
235 
IsOptionalLogEnabled()236     bool IsOptionalLogEnabled() const
237     {
238         return optionalLogEnabled_;
239     }
240 
241     void Iterate(const RootVisitor &v, const RootRangeVisitor &rv);
242 
GetHeap()243     const Heap *GetHeap() const
244     {
245         return heap_;
246     }
247 
248     void CollectGarbage(TriggerGCType gcType) const;
249 
250     void StartHeapTracking(HeapTracker *tracker);
251 
252     void StopHeapTracking();
253 
GetNativeAreaAllocator()254     NativeAreaAllocator *GetNativeAreaAllocator() const
255     {
256         return nativeAreaAllocator_.get();
257     }
258 
GetHeapRegionAllocator()259     HeapRegionAllocator *GetHeapRegionAllocator() const
260     {
261         return heapRegionAllocator_.get();
262     }
263 
GetChunk()264     Chunk *GetChunk() const
265     {
266         return const_cast<Chunk *>(&chunk_);
267     }
268     void ProcessNativeDelete(const WeakRootVisitor &visitor);
269     void ProcessReferences(const WeakRootVisitor &visitor);
270 
GetModuleManager()271     ModuleManager *GetModuleManager() const
272     {
273         return moduleManager_;
274     }
275 
GetTSManager()276     TSManager *GetTSManager() const
277     {
278         return tsManager_;
279     }
280 
GetAOTFileManager()281     AOTFileManager* PUBLIC_API GetAOTFileManager() const
282     {
283         return aotFileManager_;
284     }
285 
GetSnapshotEnv()286     SnapshotEnv *GetSnapshotEnv() const
287     {
288         return snapshotEnv_;
289     }
290 
291     void SetupRegExpResultCache();
292 
GetRegExpCache()293     JSHandle<JSTaggedValue> GetRegExpCache() const
294     {
295         return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&regexpCache_));
296     }
297 
SetRegExpCache(JSTaggedValue newCache)298     void SetRegExpCache(JSTaggedValue newCache)
299     {
300         regexpCache_ = newCache;
301     }
302 
GetJsDebuggerManager()303     tooling::JsDebuggerManager *GetJsDebuggerManager() const
304     {
305         return debuggerManager_;
306     }
307 
SetEnableForceGC(bool enable)308     void SetEnableForceGC(bool enable)
309     {
310         options_.SetEnableForceGC(enable);
311     }
312 
SetData(void * data)313     void SetData(void* data)
314     {
315         data_ = data;
316     }
317 
SetPromiseRejectCallback(PromiseRejectCallback cb)318     void SetPromiseRejectCallback(PromiseRejectCallback cb)
319     {
320         promiseRejectCallback_ = cb;
321     }
322 
GetPromiseRejectCallback()323     PromiseRejectCallback GetPromiseRejectCallback() const
324     {
325         return promiseRejectCallback_;
326     }
327 
SetNativePtrGetter(NativePtrGetter cb)328     void SetNativePtrGetter(NativePtrGetter cb)
329     {
330         nativePtrGetter_ = cb;
331     }
332 
GetNativePtrGetter()333     NativePtrGetter GetNativePtrGetter() const
334     {
335         return nativePtrGetter_;
336     }
337 
SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)338     void SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)
339     {
340         hostPromiseRejectionTracker_ = cb;
341     }
342 
SetAllowAtomicWait(bool wait)343     void SetAllowAtomicWait(bool wait)
344     {
345         AllowAtomicWait_ = wait;
346     }
347 
GetAllowAtomicWait()348     bool GetAllowAtomicWait() const
349     {
350         return AllowAtomicWait_;
351     }
352 
GetWaiterListNode()353     WaiterListNode *GetWaiterListNode()
354     {
355         return &waiterListNode_;
356     }
357 
PromiseRejectionTracker(const JSHandle<JSPromise> & promise,const JSHandle<JSTaggedValue> & reason,PromiseRejectionEvent operation)358     void PromiseRejectionTracker(const JSHandle<JSPromise> &promise,
359                                  const JSHandle<JSTaggedValue> &reason, PromiseRejectionEvent operation)
360     {
361         if (hostPromiseRejectionTracker_ != nullptr) {
362             hostPromiseRejectionTracker_(this, promise, reason, operation, data_);
363         }
364     }
365 
SetResolveBufferCallback(ResolveBufferCallback cb)366     void SetResolveBufferCallback(ResolveBufferCallback cb)
367     {
368         resolveBufferCallback_ = cb;
369     }
370 
GetResolveBufferCallback()371     ResolveBufferCallback GetResolveBufferCallback() const
372     {
373         return resolveBufferCallback_;
374     }
375 
SetConcurrentCallback(ConcurrentCallback callback,void * data)376     void SetConcurrentCallback(ConcurrentCallback callback, void *data)
377     {
378         concurrentCallback_ = callback;
379         concurrentData_ = data;
380     }
381 
382     void TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint);
383 
384     void AddConstpool(const JSPandaFile *jsPandaFile, JSTaggedValue constpool, int32_t index = 0);
385 
386     bool HasCachedConstpool(const JSPandaFile *jsPandaFile) const;
387 
388     JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index);
389 
390     JSHandle<ConstantPool> PUBLIC_API FindOrCreateConstPool(const JSPandaFile *jsPandaFile,
391                                                             panda_file::File::EntityId id);
392 
393     std::optional<std::reference_wrapper<CMap<int32_t, JSTaggedValue>>> FindConstpools(const JSPandaFile *jsPandaFile);
StoreBCOffsetInfo(const std::string & methodName,int32_t bcOffset)394     void StoreBCOffsetInfo(const std::string& methodName, int32_t bcOffset)
395     {
396         exceptionBCList_.emplace_back(std::pair<std::string, int32_t>(methodName, bcOffset));
397     }
398 
GetBCOffsetInfoList()399     std::vector<std::pair<std::string, int32_t>> GetBCOffsetInfoList() const
400     {
401         return exceptionBCList_;
402     }
403 
ClearExceptionBCList()404     void ClearExceptionBCList()
405     {
406         exceptionBCList_.clear();
407     }
408 
WorkersetInfo(EcmaVM * hostVm,EcmaVM * workerVm)409     void WorkersetInfo(EcmaVM *hostVm, EcmaVM *workerVm)
410     {
411         os::memory::LockHolder lock(mutex_);
412         auto thread = workerVm->GetJSThread();
413         if (thread != nullptr && hostVm != nullptr) {
414             auto tid = thread->GetThreadId();
415             if (tid != 0) {
416                 WorkerList_.emplace(tid, workerVm);
417             }
418         }
419     }
420 
GetWorkerVm(uint32_t tid)421     EcmaVM *GetWorkerVm(uint32_t tid) const
422     {
423         EcmaVM *workerVm = nullptr;
424         if (!WorkerList_.empty()) {
425             auto iter = WorkerList_.find(tid);
426             if (iter != WorkerList_.end()) {
427                 workerVm = iter->second;
428             }
429         }
430         return workerVm;
431     }
432 
DeleteWorker(EcmaVM * hostVm,EcmaVM * workerVm)433     bool DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm)
434     {
435         os::memory::LockHolder lock(mutex_);
436         auto thread = workerVm->GetJSThread();
437         if (hostVm != nullptr && thread != nullptr) {
438             auto tid = thread->GetThreadId();
439             if (tid == 0) {
440                 return false;
441             }
442             auto iter = WorkerList_.find(tid);
443             if (iter != WorkerList_.end()) {
444                 WorkerList_.erase(iter);
445                 return true;
446             }
447             return false;
448         }
449         return false;
450     }
451 
IsWorkerThread()452     bool IsWorkerThread()
453     {
454         return options_.IsWorker();
455     }
456 
IsBundlePack()457     bool IsBundlePack() const
458     {
459         return isBundlePack_;
460     }
461 
SetIsBundlePack(bool value)462     void SetIsBundlePack(bool value)
463     {
464         isBundlePack_ = value;
465     }
466 
467 #if !WIN_OR_MAC_OR_IOS_PLATFORM
468     void DeleteHeapProfile();
469     HeapProfilerInterface *GetOrNewHeapProfile();
470 #endif
471 
SetAssetPath(const CString & assetPath)472     void SetAssetPath(const CString &assetPath)
473     {
474         assetPath_ = assetPath;
475     }
476 
GetAssetPath()477     CString GetAssetPath() const
478     {
479         return assetPath_;
480     }
481 
SetBundleName(const CString & bundleName)482     void SetBundleName(const CString &bundleName)
483     {
484         bundleName_ = bundleName;
485     }
486 
GetBundleName()487     CString GetBundleName() const
488     {
489         return bundleName_;
490     }
491 
SetModuleName(const CString & moduleName)492     void SetModuleName(const CString &moduleName)
493     {
494         moduleName_ = moduleName;
495     }
496 
GetModuleName()497     CString GetModuleName() const
498     {
499         return moduleName_;
500     }
501 
502 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
GetProfiler()503     CpuProfiler *GetProfiler() const
504     {
505         return profiler_;
506     }
507 
SetProfiler(CpuProfiler * profiler)508     void SetProfiler(CpuProfiler *profiler)
509     {
510         profiler_ = profiler;
511     }
512 #endif
513 
GetPGOProfiler()514     PGOProfiler *GetPGOProfiler() const
515     {
516         return pgoProfiler_;
517     }
518 
519     bool FindCatchBlock(Method *method, uint32_t pc) const;
520 
521     void PreFork();
522     void PostFork();
523 
524     // For Internal Native MethodLiteral.
525     JSTaggedValue GetMethodByIndex(MethodIndex idx);
526 
GetQuickFixManager()527     QuickFixManager *GetQuickFixManager() const
528     {
529         return quickFixManager_;
530     }
531 
532     JSTaggedValue ExecuteAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp,
533                              OptimizedEntryFrame::CallType callType);
534 
535     // For icu objects cache
536     void SetIcuFormatterToCache(IcuFormatterType type, const std::string &locale, void *icuObj,
537                                 IcuDeleteEntry deleteEntry = nullptr)
538     {
539         EcmaVM::IcuFormatter icuFormatter = IcuFormatter(locale, icuObj, deleteEntry);
540         icuObjCache_.insert_or_assign(type, std::move(icuFormatter));
541     }
542 
GetIcuFormatterFromCache(IcuFormatterType type,std::string locale)543     void *GetIcuFormatterFromCache(IcuFormatterType type, std::string locale)
544     {
545         auto iter = icuObjCache_.find(type);
546         if (iter != icuObjCache_.end()) {
547             EcmaVM::IcuFormatter icuFormatter = iter->second;
548             if (icuFormatter.locale == locale) {
549                 return icuFormatter.icuObj;
550             }
551         }
552         return nullptr;
553     }
554 
ClearIcuCache()555     void ClearIcuCache()
556     {
557         auto iter = icuObjCache_.begin();
558         while (iter != icuObjCache_.end()) {
559             EcmaVM::IcuFormatter icuFormatter = iter->second;
560             IcuDeleteEntry deleteEntry = icuFormatter.deleteEntry;
561             if (deleteEntry != nullptr) {
562                 deleteEntry(icuFormatter.icuObj, this);
563             }
564             iter->second = EcmaVM::IcuFormatter{};
565             iter++;
566         }
567     }
568 
GetOptCodeProfiler()569     OptCodeProfiler *GetOptCodeProfiler() const
570     {
571         return optCodeProfiler_;
572     }
573 
574     void HandleUncaughtException(TaggedObject *exception);
575 
576 protected:
577 
578     void PrintJSErrorInfo(const JSHandle<JSTaggedValue> &exceptionInfo);
579 
580 private:
581     void SetGlobalEnv(GlobalEnv *global);
582 
583     void SetMicroJobQueue(job::MicroJobQueue *queue);
584 
585     Expected<JSTaggedValue, bool> InvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile, std::string_view entryPoint,
586                                                        bool excuteFromJob = false);
587 
588     JSTaggedValue InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc, JSHandle<JSTaggedValue> &thisArg,
589                                           const JSPandaFile *jsPandaFile, std::string_view entryPoint);
590 
591     void CJSExecution(JSHandle<JSFunction> &func, JSHandle<JSTaggedValue> &thisArg,
592                       const JSPandaFile *jsPandaFile);
593 
594     void InitializeEcmaScriptRunStat();
595 
596     void ClearBufferData();
597 
598     void LoadAOTFiles(const std::string& aotFileName);
599     void LoadStubFile();
600 
601     void CheckStartCpuProfiler();
602 
603     // For Internal Native MethodLiteral.
604     void GenerateInternalNativeMethods();
605 
606     NO_MOVE_SEMANTIC(EcmaVM);
607     NO_COPY_SEMANTIC(EcmaVM);
608 
609     // VM startup states.
610     JSRuntimeOptions options_;
611     bool icEnabled_ {true};
612     bool initialized_ {false};
613     bool globalConstInitialized_ {false};
614     GCStats *gcStats_ {nullptr};
615     bool isUncaughtExceptionRegistered_ {false};
616     // VM memory management.
617     EcmaStringTable *stringTable_ {nullptr};
618     std::unique_ptr<NativeAreaAllocator> nativeAreaAllocator_;
619     std::unique_ptr<HeapRegionAllocator> heapRegionAllocator_;
620     Chunk chunk_;
621     Heap *heap_ {nullptr};
622     ObjectFactory *factory_ {nullptr};
623     CList<JSNativePointer *> nativePointerList_;
624     // VM execution states.
625     JSThread *thread_ {nullptr};
626     RegExpParserCache *regExpParserCache_ {nullptr};
627     JSTaggedValue globalEnv_ {JSTaggedValue::Hole()};
628     JSTaggedValue regexpCache_ {JSTaggedValue::Hole()};
629     JSTaggedValue microJobQueue_ {JSTaggedValue::Hole()};
630     EcmaRuntimeStat *runtimeStat_ {nullptr};
631 
632     // For framewrok file snapshot.
633     CString snapshotFileName_;
634     CString frameworkAbcFileName_;
635     JSTaggedValue frameworkProgram_ {JSTaggedValue::Hole()};
636     const JSPandaFile *frameworkPandaFile_ {nullptr};
637     CMap<const JSPandaFile *, CMap<int32_t, JSTaggedValue>> cachedConstpools_ {};
638 
639     // VM resources.
640     ModuleManager *moduleManager_ {nullptr};
641     TSManager *tsManager_ {nullptr};
642     SnapshotEnv *snapshotEnv_ {nullptr};
643     bool optionalLogEnabled_ {false};
644     AOTFileManager *aotFileManager_ {nullptr};
645 
646     // Debugger
647     tooling::JsDebuggerManager *debuggerManager_ {nullptr};
648     // merge abc
649     bool isBundlePack_ {true}; // isBundle means app compile mode is JSBundle
650 #if !WIN_OR_MAC_OR_IOS_PLATFORM
651     HeapProfilerInterface *heapProfile_ {nullptr};
652 #endif
653     CString assetPath_;
654     CString bundleName_;
655     CString moduleName_;
656     // Registered Callbacks
657     PromiseRejectCallback promiseRejectCallback_ {nullptr};
658     HostPromiseRejectionTracker hostPromiseRejectionTracker_ {nullptr};
659     NativePtrGetter nativePtrGetter_ {nullptr};
660     void* data_ {nullptr};
661 
662     bool isProcessingPendingJob_ = false;
663 	// atomics
664     bool AllowAtomicWait_ {true};
665     WaiterListNode waiterListNode_;
666     std::vector<std::pair<std::string, int32_t>> exceptionBCList_;
667 
668     // CJS resolve path Callbacks
669     ResolvePathCallback resolvePathCallback_ {nullptr};
670     ResolveBufferCallback resolveBufferCallback_ {nullptr};
671 
672     // Concurrent taskpool callback and data
673     ConcurrentCallback concurrentCallback_ {nullptr};
674     void *concurrentData_ {nullptr};
675 
676     // vm parameter configurations
677     EcmaParamConfiguration ecmaParamConfiguration_;
678 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
679     CpuProfiler *profiler_ {nullptr};
680 #endif
681 
682     // For Native MethodLiteral
683     static void *InternalMethodTable[static_cast<uint8_t>(MethodIndex::METHOD_END)];
684     CVector<JSTaggedValue> internalNativeMethods_;
685 
686     // For repair patch.
687     QuickFixManager *quickFixManager_ {nullptr};
688 
689     // PGO Profiler
690     PGOProfiler *pgoProfiler_ {nullptr};
691 
692     // opt code Profiler
693     OptCodeProfiler *optCodeProfiler_ {nullptr};
694 
695     // For icu objects cache
696     struct IcuFormatter {
697         std::string locale;
698         void *icuObj {nullptr};
699         IcuDeleteEntry deleteEntry {nullptr};
700 
701         IcuFormatter() = default;
702         IcuFormatter(const std::string &locale, void *icuObj, IcuDeleteEntry deleteEntry = nullptr)
localeIcuFormatter703             : locale(locale), icuObj(icuObj), deleteEntry(deleteEntry) {}
704     };
705     std::unordered_map<IcuFormatterType, IcuFormatter> icuObjCache_;
706 
707     friend class Snapshot;
708     friend class SnapshotProcessor;
709     friend class ObjectFactory;
710     friend class ValueSerializer;
711     friend class panda::JSNApi;
712     friend class JSPandaFileExecutor;
713     CMap<uint32_t, EcmaVM *> WorkerList_ {};
714     os::memory::Mutex mutex_;
715     void *loop_ {nullptr};
716 };
717 }  // namespace ecmascript
718 }  // namespace panda
719 
720 #endif
721