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 #ifndef ECMASCRIPT_ECMA_CONTEXT_H 16 #define ECMASCRIPT_ECMA_CONTEXT_H 17 18 #include <optional> 19 #include "ecmascript/base/config.h" 20 #include "ecmascript/common.h" 21 #include "ecmascript/dfx/vmstat/opt_code_profiler.h" 22 #include "ecmascript/frames.h" 23 #include "ecmascript/js_handle.h" 24 #include "ecmascript/js_tagged_value.h" 25 #include "ecmascript/mem/c_containers.h" 26 #include "ecmascript/mem/visitor.h" 27 #include "ecmascript/patch/patch_loader.h" 28 #include "ecmascript/regexp/regexp_parser_cache.h" 29 #include "ecmascript/waiter_list.h" 30 #include "global_handle_collection.h" 31 #include "libpandafile/file.h" 32 33 namespace panda { 34 class JSNApi; 35 namespace panda_file { 36 class File; 37 } // namespace panda_file 38 39 namespace ecmascript { 40 class GlobalEnv; 41 class ObjectFactory; 42 class EcmaRuntimeStat; 43 class RegExpParserCache; 44 class JSPandaFileManager; 45 class JSPandaFile; 46 class ConstantPool; 47 class JSPromise; 48 class RegExpExecResultCache; 49 class EcmaHandleScope; 50 class GlobalIndexMap; 51 enum class PromiseRejectionEvent : uint8_t; 52 53 template<typename T> 54 class JSHandle; 55 class JSThread; 56 class JSFunction; 57 class JSPromise; 58 class JSTaggedValue; 59 class EcmaVM; 60 class ModuleManager; 61 class TSManager; 62 class AOTFileManager; 63 class QuickFixManager; 64 class OptCodeProfiler; 65 struct CJSInfo; 66 67 namespace job { 68 class MicroJobQueue; 69 } // namespace job 70 namespace tooling { 71 class JsDebuggerManager; 72 } // namespace tooling 73 namespace kungfu { 74 class PGOTypeManager; 75 } // namespace kungfu 76 77 enum class IcuFormatterType { 78 SIMPLE_DATE_FORMAT_DEFAULT, 79 SIMPLE_DATE_FORMAT_DATE, 80 SIMPLE_DATE_FORMAT_TIME, 81 NUMBER_FORMATTER, 82 COLLATOR, 83 ICU_FORMATTER_TYPE_COUNT 84 }; 85 86 using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm, 87 const JSHandle<JSPromise> promise, 88 const JSHandle<JSTaggedValue> reason, 89 PromiseRejectionEvent operation, 90 void* data); 91 using PromiseRejectCallback = void (*)(void* info); 92 using IcuDeleteEntry = void(*)(void *pointer, void *data); 93 class EcmaContext { 94 public: 95 static EcmaContext *CreateAndInitialize(JSThread *thread); 96 static void CheckAndDestroy(JSThread *thread, EcmaContext *context); 97 98 static EcmaContext *Create(JSThread *thread); 99 static bool Destroy(EcmaContext *context); 100 101 EcmaContext(JSThread *thread); 102 ~EcmaContext(); 103 GetEcmaVM()104 EcmaVM *GetEcmaVM() const 105 { 106 return vm_; 107 } 108 109 bool Initialize(); 110 IsExecutingPendingJob()111 bool IsExecutingPendingJob() const 112 { 113 return isProcessingPendingJob_.load(); 114 } 115 116 bool HasPendingJob(); 117 118 bool ExecutePromisePendingJob(); 119 ConstCast(const EcmaContext * context)120 static EcmaContext *ConstCast(const EcmaContext *context) 121 { 122 return const_cast<EcmaContext *>(context); 123 } 124 IsInitialized()125 bool IsInitialized() const 126 { 127 return initialized_; 128 } 129 GetModuleManager()130 ModuleManager *GetModuleManager() const 131 { 132 return moduleManager_; 133 } 134 GetTSManager()135 TSManager *GetTSManager() const 136 { 137 return tsManager_; 138 } 139 GetPTManager()140 kungfu::PGOTypeManager *GetPTManager() const 141 { 142 return ptManager_; 143 } 144 145 void SetTSManager(TSManager *set); 146 GetJSThread()147 ARK_INLINE JSThread *GetJSThread() const 148 { 149 return thread_; 150 } GetPromiseRejectCallback()151 PromiseRejectCallback GetPromiseRejectCallback() const 152 { 153 return promiseRejectCallback_; 154 } 155 SetPromiseRejectCallback(PromiseRejectCallback cb)156 void SetPromiseRejectCallback(PromiseRejectCallback cb) 157 { 158 promiseRejectCallback_ = cb; 159 } 160 SetData(void * data)161 void SetData(void* data) 162 { 163 data_ = data; 164 } 165 PromiseRejectionTracker(const JSHandle<JSPromise> & promise,const JSHandle<JSTaggedValue> & reason,PromiseRejectionEvent operation)166 void PromiseRejectionTracker(const JSHandle<JSPromise> &promise, 167 const JSHandle<JSTaggedValue> &reason, PromiseRejectionEvent operation) 168 { 169 if (hostPromiseRejectionTracker_ != nullptr) { 170 hostPromiseRejectionTracker_(vm_, promise, reason, operation, data_); 171 } 172 } 173 SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)174 void SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb) 175 { 176 hostPromiseRejectionTracker_ = cb; 177 } 178 void SetupRegExpResultCache(); 179 void SetupNumberToStringResultCache(); 180 void SetupStringSplitResultCache(); 181 void SetupStringToListResultCache(); GetRegExpCache()182 JSHandle<JSTaggedValue> GetRegExpCache() const 183 { 184 return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(®expCache_)); 185 } 186 GetRegExpParserCache()187 RegExpParserCache *GetRegExpParserCache() const 188 { 189 ASSERT(regExpParserCache_ != nullptr); 190 return regExpParserCache_; 191 } 192 SetRegExpCache(JSTaggedValue newCache)193 void SetRegExpCache(JSTaggedValue newCache) 194 { 195 regexpCache_ = newCache; 196 } GetExpCacheAddress()197 uintptr_t GetExpCacheAddress() 198 { 199 return reinterpret_cast<uintptr_t>(®expCache_); 200 } 201 202 void SetupRegExpGlobalResult(); 203 GetRegExpGlobalResult()204 JSHandle<JSTaggedValue> GetRegExpGlobalResult() const 205 { 206 return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(®expGlobal_)); 207 } 208 SetRegExpGlobalResult(JSTaggedValue newResult)209 void SetRegExpGlobalResult(JSTaggedValue newResult) 210 { 211 regexpGlobal_ = newResult; 212 } 213 GetWaiterListNode()214 WaiterListNode *GetWaiterListNode() 215 { 216 return &waiterListNode_; 217 } 218 SetAllowAtomicWait(bool wait)219 void SetAllowAtomicWait(bool wait) 220 { 221 AllowAtomicWait_ = wait; 222 } 223 GetAllowAtomicWait()224 bool GetAllowAtomicWait() const 225 { 226 return AllowAtomicWait_; 227 } GetNumberToStringResultCache()228 JSHandle<JSTaggedValue> GetNumberToStringResultCache() const 229 { 230 return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&numberToStringResultCache_)); 231 } 232 SetNumberToStringResultCache(JSTaggedValue newCache)233 void SetNumberToStringResultCache(JSTaggedValue newCache) 234 { 235 numberToStringResultCache_ = newCache; 236 } 237 GetStringSplitResultCache()238 JSHandle<JSTaggedValue> GetStringSplitResultCache() const 239 { 240 return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&stringSplitResultCache_)); 241 } 242 GetStringToListResultCache()243 JSHandle<JSTaggedValue> GetStringToListResultCache() const 244 { 245 return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&stringToListResultCache_)); 246 } 247 SetStringSplitResultCache(JSTaggedValue newCache)248 void SetStringSplitResultCache(JSTaggedValue newCache) 249 { 250 stringSplitResultCache_ = newCache; 251 } 252 JSHandle<ecmascript::JSTaggedValue> GetAndClearEcmaUncaughtException() const; 253 JSHandle<ecmascript::JSTaggedValue> GetEcmaUncaughtException() const; 254 void EnableUserUncaughtErrorHandler(); 255 256 void AddConstpool(const JSPandaFile *jsPandaFile, JSTaggedValue constpool, int32_t index = 0); 257 258 bool HasCachedConstpool(const JSPandaFile *jsPandaFile) const; 259 260 JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, int32_t index); 261 // For new version instruction. 262 JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id); 263 JSTaggedValue FindConstpoolWithAOT(const JSPandaFile *jsPandaFile, int32_t index); 264 std::optional<std::reference_wrapper<CMap<int32_t, JSTaggedValue>>> FindConstpools( 265 const JSPandaFile *jsPandaFile); 266 267 JSHandle<ConstantPool> PUBLIC_API FindOrCreateConstPool(const JSPandaFile *jsPandaFile, 268 panda_file::File::EntityId id); 269 void CreateAllConstpool(const JSPandaFile *jsPandaFile); 270 271 void HandleUncaughtException(JSTaggedValue exception); 272 void ProcessNativeDelete(const WeakRootVisitor &visitor); 273 void ProcessReferences(const WeakRootVisitor &visitor); 274 JSHandle<GlobalEnv> GetGlobalEnv() const; GlobalEnvIsHole()275 bool GlobalEnvIsHole() 276 { 277 return globalEnv_.IsHole(); 278 } 279 280 JSHandle<job::MicroJobQueue> GetMicroJobQueue() const; 281 282 static void PrintJSErrorInfo(JSThread *thread, const JSHandle<JSTaggedValue> &exceptionInfo); 283 void Iterate(const RootVisitor &v, const RootRangeVisitor &rv); 284 static void MountContext(JSThread *thread); 285 static void UnmountContext(JSThread *thread); 286 void SetMicroJobQueue(job::MicroJobQueue *queue); 287 void SetGlobalEnv(GlobalEnv *global); 288 void PrintOptStat(); 289 GetOptCodeProfiler()290 OptCodeProfiler *GetOptCodeProfiler() const 291 { 292 return optCodeProfiler_; 293 } 294 GetTypdOpProfiler()295 TypedOpProfiler *GetTypdOpProfiler() const 296 { 297 return typedOpProfiler_; 298 } 299 300 // For icu objects cache 301 void SetIcuFormatterToCache(IcuFormatterType type, const std::string &locale, void *icuObj, 302 IcuDeleteEntry deleteEntry = nullptr) 303 { 304 EcmaContext::IcuFormatter icuFormatter = IcuFormatter(locale, icuObj, deleteEntry); 305 icuObjCache_[static_cast<int>(type)] = icuFormatter; 306 } 307 GetIcuFormatterFromCache(IcuFormatterType type,std::string & locale)308 ARK_INLINE void *GetIcuFormatterFromCache(IcuFormatterType type, std::string &locale) 309 { 310 auto &icuFormatter = icuObjCache_[static_cast<int>(type)]; 311 if (icuFormatter.locale == locale) { 312 return icuFormatter.icuObj; 313 } 314 return nullptr; 315 } 316 ClearIcuCache()317 void ClearIcuCache() 318 { 319 for (uint32_t i = 0; i < static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT); i++) { 320 auto &icuFormatter = icuObjCache_[i]; 321 IcuDeleteEntry deleteEntry = icuFormatter.deleteEntry; 322 if (deleteEntry != nullptr) { 323 deleteEntry(icuFormatter.icuObj, vm_); 324 } 325 icuFormatter = EcmaContext::IcuFormatter{}; 326 } 327 } 328 GetAOTFileManager()329 AOTFileManager *GetAOTFileManager() const 330 { 331 return aotFileManager_; 332 } 333 GetRuntimeStat()334 EcmaRuntimeStat *GetRuntimeStat() const 335 { 336 return runtimeStat_; 337 } 338 339 void SetRuntimeStatEnable(bool flag); 340 void InitializeEcmaScriptRunStat(); 341 void DumpAOTInfo() const DUMP_API_ATTR; 342 343 JSTaggedValue ExecuteAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp, 344 bool needPushUndefined); 345 void LoadStubFile(); 346 GetHandleScopeStorageNext()347 JSTaggedType *GetHandleScopeStorageNext() const 348 { 349 return handleScopeStorageNext_; 350 } 351 SetHandleScopeStorageNext(JSTaggedType * value)352 void SetHandleScopeStorageNext(JSTaggedType *value) 353 { 354 handleScopeStorageNext_ = value; 355 } 356 GetHandleScopeStorageEnd()357 JSTaggedType *GetHandleScopeStorageEnd() const 358 { 359 return handleScopeStorageEnd_; 360 } 361 SetHandleScopeStorageEnd(JSTaggedType * value)362 void SetHandleScopeStorageEnd(JSTaggedType *value) 363 { 364 handleScopeStorageEnd_ = value; 365 } 366 GetCurrentHandleStorageIndex()367 int GetCurrentHandleStorageIndex() const 368 { 369 return currentHandleStorageIndex_; 370 } 371 HandleScopeCountAdd()372 void HandleScopeCountAdd() 373 { 374 handleScopeCount_++; 375 } 376 HandleScopeCountDec()377 void HandleScopeCountDec() 378 { 379 handleScopeCount_--; 380 } 381 SetLastHandleScope(EcmaHandleScope * scope)382 void SetLastHandleScope(EcmaHandleScope *scope) 383 { 384 lastHandleScope_ = scope; 385 } 386 GetLastHandleScope()387 EcmaHandleScope *GetLastHandleScope() const 388 { 389 return lastHandleScope_; 390 } 391 392 size_t IterateHandle(const RootRangeVisitor &rangeVisitor); 393 uintptr_t *ExpandHandleStorage(); 394 void ShrinkHandleStorage(int prevIndex); 395 GetCurrentFrame()396 JSTaggedType *GetCurrentFrame() const 397 { 398 return currentFrame_; 399 } 400 GetLeaveFrame()401 JSTaggedType *GetLeaveFrame() const 402 { 403 return leaveFrame_; 404 } 405 GetLastFp()406 JSTaggedType *GetLastFp() const 407 { 408 return lastFp_; 409 } 410 SetFramePointers(JSTaggedType * currentFrame,JSTaggedType * leaveFrame,JSTaggedType * lastFp)411 void SetFramePointers(JSTaggedType *currentFrame, JSTaggedType *leaveFrame, JSTaggedType *lastFp) 412 { 413 currentFrame_ = currentFrame; 414 leaveFrame_ = leaveFrame; 415 lastFp_ = lastFp; 416 } SetFrameBase(JSTaggedType * frameBase)417 void SetFrameBase(JSTaggedType *frameBase) 418 { 419 frameBase_ = frameBase; 420 } GetFrameBase()421 JSTaggedType *GetFrameBase() const 422 { 423 return frameBase_; 424 } 425 SetStackStart(uint64_t stackStart)426 void SetStackStart(uint64_t stackStart) 427 { 428 stackStart_ = stackStart; 429 } GetStackStart()430 uint64_t GetStackStart() const 431 { 432 return stackStart_; 433 } SetStackLimit(uint64_t stackLimit)434 void SetStackLimit(uint64_t stackLimit) 435 { 436 stackLimit_ = stackLimit; 437 } GetStackLimit()438 uint64_t GetStackLimit() const 439 { 440 return stackLimit_; 441 } 442 GetPropertiesCache()443 PropertiesCache *GetPropertiesCache() const 444 { 445 return propertiesCache_; 446 } 447 void ClearBufferData(); GlobalConstants()448 const GlobalEnvConstants *GlobalConstants() const 449 { 450 return &globalConst_; 451 } 452 AddPatchModule(const CString & recordName,const JSHandle<JSTaggedValue> moduleRecord)453 void AddPatchModule(const CString &recordName, const JSHandle<JSTaggedValue> moduleRecord) 454 { 455 cachedPatchModules_.emplace(recordName, moduleRecord); 456 } FindPatchModule(const CString & recordName)457 JSHandle<JSTaggedValue> FindPatchModule(const CString &recordName) const 458 { 459 auto iter = cachedPatchModules_.find(recordName); 460 if (iter != cachedPatchModules_.end()) { 461 return iter->second; 462 } 463 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole()); 464 } ClearPatchModules()465 void ClearPatchModules() 466 { 467 GlobalHandleCollection gloalHandleCollection(thread_); 468 for (auto &item : cachedPatchModules_) { 469 gloalHandleCollection.Dispose(item.second); 470 } 471 cachedPatchModules_.clear(); 472 } 473 GetStageOfHotReload()474 StageOfHotReload GetStageOfHotReload() const 475 { 476 return stageOfHotReload_; 477 } SetStageOfHotReload(StageOfHotReload stageOfHotReload)478 void SetStageOfHotReload(StageOfHotReload stageOfHotReload) 479 { 480 stageOfHotReload_ = stageOfHotReload; 481 } 482 483 bool JoinStackPushFastPath(JSHandle<JSTaggedValue> receiver); 484 bool JoinStackPush(JSHandle<JSTaggedValue> receiver); 485 void JoinStackPopFastPath(JSHandle<JSTaggedValue> receiver); 486 void JoinStackPop(JSHandle<JSTaggedValue> receiver); 487 SetJsonStringifyCache(size_t index,CVector<std::pair<CString,int>> & value)488 void SetJsonStringifyCache(size_t index, CVector<std::pair<CString, int>> &value) 489 { 490 stringifyCache_[index] = value; 491 } 492 GetJsonStringifyCache(size_t index)493 CVector<std::pair<CString, int>> GetJsonStringifyCache(size_t index) 494 { 495 return stringifyCache_[index]; 496 } 497 IsAotEntry()498 bool IsAotEntry() 499 { 500 return isAotEntry_; 501 } 502 503 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const; 504 private: 505 void CJSExecution(JSHandle<JSFunction> &func, JSHandle<JSTaggedValue> &thisArg, 506 const JSPandaFile *jsPandaFile, std::string_view entryPoint); 507 JSTaggedValue InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc, JSHandle<JSTaggedValue> &thisArg, 508 const JSPandaFile *jsPandaFile, std::string_view entryPoint, 509 CJSInfo *cjsInfo = nullptr); 510 Expected<JSTaggedValue, bool> InvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile, std::string_view entryPoint, 511 bool excuteFromJob = false); 512 Expected<JSTaggedValue, bool> InvokeEcmaEntrypointForHotReload( 513 const JSPandaFile *jsPandaFile, std::string_view entryPoint, bool excuteFromJob); 514 Expected<JSTaggedValue, bool> CommonInvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile, 515 std::string_view entryPoint, JSHandle<JSFunction> &func); 516 bool LoadAOTFiles(const std::string &aotFileName); 517 void RelocateConstantString(const JSPandaFile *jsPandaFile); 518 NO_MOVE_SEMANTIC(EcmaContext); 519 NO_COPY_SEMANTIC(EcmaContext); 520 521 PropertiesCache *propertiesCache_ {nullptr}; 522 JSThread *thread_ {nullptr}; 523 EcmaVM *vm_ {nullptr}; 524 525 bool isUncaughtExceptionRegistered_ {false}; 526 bool initialized_ {false}; 527 std::atomic<bool> isProcessingPendingJob_ {false}; 528 ObjectFactory *factory_ {nullptr}; 529 530 // VM execution states. 531 RegExpParserCache *regExpParserCache_ {nullptr}; 532 JSTaggedValue numberToStringResultCache_ {JSTaggedValue::Hole()}; 533 JSTaggedValue stringSplitResultCache_ {JSTaggedValue::Hole()}; 534 JSTaggedValue stringToListResultCache_ {JSTaggedValue::Hole()}; 535 JSTaggedValue globalEnv_ {JSTaggedValue::Hole()}; 536 JSTaggedValue pointerToIndexDictionary_ {JSTaggedValue::Hole()}; 537 JSTaggedValue regexpCache_ {JSTaggedValue::Hole()}; 538 JSTaggedValue regexpGlobal_ {JSTaggedValue::Hole()}; 539 JSTaggedValue microJobQueue_ {JSTaggedValue::Hole()}; 540 EcmaRuntimeStat *runtimeStat_ {nullptr}; 541 542 CMap<const JSPandaFile *, CMap<int32_t, JSTaggedValue>> cachedConstpools_ {}; 543 544 // for HotReload of module. 545 CMap<CString, JSHandle<JSTaggedValue>> cachedPatchModules_ {}; 546 StageOfHotReload stageOfHotReload_ = StageOfHotReload::INITIALIZE_STAGE_OF_HOTRELOAD; 547 548 // VM resources. 549 ModuleManager *moduleManager_ {nullptr}; 550 TSManager *tsManager_ {nullptr}; 551 kungfu::PGOTypeManager *ptManager_ {nullptr}; 552 AOTFileManager *aotFileManager_ {nullptr}; 553 554 // atomics 555 bool AllowAtomicWait_ {true}; 556 WaiterListNode waiterListNode_; 557 558 // Registered Callbacks 559 PromiseRejectCallback promiseRejectCallback_ {nullptr}; 560 HostPromiseRejectionTracker hostPromiseRejectionTracker_ {nullptr}; 561 void* data_{nullptr}; 562 563 // opt code Profiler 564 OptCodeProfiler *optCodeProfiler_ {nullptr}; 565 566 // opt code loop hoist 567 TypedOpProfiler *typedOpProfiler_ {nullptr}; 568 569 // For icu objects cache 570 struct IcuFormatter { 571 std::string locale; 572 void *icuObj {nullptr}; 573 IcuDeleteEntry deleteEntry {nullptr}; 574 575 IcuFormatter() = default; 576 IcuFormatter(const std::string &locale, void *icuObj, IcuDeleteEntry deleteEntry = nullptr) localeIcuFormatter577 : locale(locale), icuObj(icuObj), deleteEntry(deleteEntry) {} 578 }; 579 IcuFormatter icuObjCache_[static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT)]; 580 // Handlescope 581 static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10; 582 static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2; 583 static constexpr int32_t MIN_HANDLE_STORAGE_SIZE = 2; 584 JSTaggedType *handleScopeStorageNext_ {nullptr}; 585 JSTaggedType *handleScopeStorageEnd_ {nullptr}; 586 std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> handleStorageNodes_ {}; 587 int32_t currentHandleStorageIndex_ {-1}; 588 int32_t handleScopeCount_ {0}; 589 EcmaHandleScope *lastHandleScope_ {nullptr}; 590 // Frame pointer 591 JSTaggedType *currentFrame_ {nullptr}; 592 JSTaggedType *leaveFrame_ {nullptr}; 593 JSTaggedType *lastFp_ {nullptr}; 594 JSTaggedType *frameBase_ {nullptr}; 595 uint64_t stackStart_ {0}; 596 uint64_t stackLimit_ {0}; 597 GlobalEnvConstants globalConst_; 598 // Join Stack 599 static constexpr uint32_t MIN_JOIN_STACK_SIZE = 2; 600 CVector<JSTaggedValue> joinStack_ {JSTaggedValue::Hole(), JSTaggedValue::Hole()}; 601 // json stringify cache 602 static constexpr uint32_t STRINGIFY_CACHE_SIZE = 64; 603 std::array<CVector<std::pair<CString, int>>, STRINGIFY_CACHE_SIZE> stringifyCache_ {}; 604 bool isAotEntry_ { false }; 605 606 friend class EcmaHandleScope; 607 friend class JSPandaFileExecutor; 608 friend class ObjectFactory; 609 friend class panda::JSNApi; 610 friend class AOTFileManager; 611 friend class GlobalIndexMap; 612 }; 613 } // namespace ecmascript 614 } // namespace panda 615 #endif // ECMASCRIPT_ECMA_CONTEXT_H 616