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>(®expCache_)); 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