1/*
2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#ifndef ECMASCRIPT_ECMA_CONTEXT_H
16#define ECMASCRIPT_ECMA_CONTEXT_H
17
18#include <cstdint>
19#include <optional>
20#include "ecmascript/base/config.h"
21#include "ecmascript/common.h"
22#include "ecmascript/js_handle.h"
23#include "ecmascript/js_tagged_value.h"
24#include "ecmascript/mem/c_containers.h"
25#include "ecmascript/mem/visitor.h"
26#include "ecmascript/patch/patch_loader.h"
27#include "ecmascript/stackmap/ark_stackmap.h"
28#include "ecmascript/waiter_list.h"
29#include "global_handle_collection.h"
30#include "libpandafile/file.h"
31
32namespace panda {
33class JSNApi;
34namespace panda_file {
35class File;
36}  // namespace panda_file
37
38namespace ecmascript {
39class GlobalEnv;
40class ObjectFactory;
41class EcmaRuntimeStat;
42class RegExpParserCache;
43class JSPandaFileManager;
44class JSPandaFile;
45class ConstantPool;
46class JSPromise;
47class RegExpExecResultCache;
48class EcmaHandleScope;
49class GlobalIndexMap;
50class SustainingJSHandleList;
51class SustainingJSHandle;
52enum class PromiseRejectionEvent : uint8_t;
53enum class CompareStringsOption : uint8_t;
54
55template<typename T>
56class JSHandle;
57class JSThread;
58class JSFunction;
59class JSPromise;
60class JSTaggedValue;
61class EcmaVM;
62class ModuleManager;
63class AOTFileManager;
64class QuickFixManager;
65class OptCodeProfiler;
66class TypedOpProfiler;
67class AbcBufferCache;
68struct CJSInfo;
69class FunctionProtoTransitionTable;
70class ModuleLogger;
71
72namespace job {
73class MicroJobQueue;
74}  // namespace job
75namespace tooling {
76class JsDebuggerManager;
77}  // namespace tooling
78namespace kungfu {
79class PGOTypeManager;
80} // namespace kungfu
81
82enum class IcuFormatterType {
83    SIMPLE_DATE_FORMAT_DEFAULT,
84    SIMPLE_DATE_FORMAT_DATE,
85    SIMPLE_DATE_FORMAT_TIME,
86    NUMBER_FORMATTER,
87    COLLATOR,
88    ICU_FORMATTER_TYPE_COUNT
89};
90
91using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
92                                             const JSHandle<JSPromise> promise,
93                                             const JSHandle<JSTaggedValue> reason,
94                                             PromiseRejectionEvent operation,
95                                             void* data);
96using PromiseRejectCallback = void (*)(void* info);
97#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
98using JsAotReaderCallback = std::function<bool(std::string fileName, uint8_t **buff, size_t *buffSize)>;
99#endif
100class EcmaContext {
101public:
102    static EcmaContext *CreateAndInitialize(JSThread *thread);
103    static void CheckAndDestroy(JSThread *thread, EcmaContext *context);
104
105    static EcmaContext *Create(JSThread *thread);
106    static bool Destroy(EcmaContext *context);
107
108    EcmaContext(JSThread *thread);
109    ~EcmaContext();
110
111    EcmaVM *GetEcmaVM() const
112    {
113        return vm_;
114    }
115
116    bool Initialize();
117
118    bool IsExecutingPendingJob() const
119    {
120        return isProcessingPendingJob_.load();
121    }
122
123    bool HasPendingJob();
124
125    bool ExecutePromisePendingJob();
126
127    static EcmaContext *ConstCast(const EcmaContext *context)
128    {
129        return const_cast<EcmaContext *>(context);
130    }
131
132    bool IsInitialized() const
133    {
134        return initialized_;
135    }
136
137    ModuleManager *GetModuleManager() const
138    {
139        return moduleManager_;
140    }
141
142    AbcBufferCache *GetAbcBufferCache() const
143    {
144        return abcBufferCache_;
145    }
146
147    kungfu::PGOTypeManager *GetPTManager() const
148    {
149        return ptManager_;
150    }
151
152    ARK_INLINE JSThread *GetJSThread() const
153    {
154        return thread_;
155    }
156    PromiseRejectCallback GetPromiseRejectCallback() const
157    {
158        return promiseRejectCallback_;
159    }
160
161    void SetPromiseRejectCallback(PromiseRejectCallback cb)
162    {
163        promiseRejectCallback_ = cb;
164    }
165
166    void SetData(void* data)
167    {
168        data_ = data;
169    }
170
171    void PromiseRejectionTracker(const JSHandle<JSPromise> &promise,
172                                 const JSHandle<JSTaggedValue> &reason, PromiseRejectionEvent operation)
173    {
174        if (hostPromiseRejectionTracker_ != nullptr) {
175            hostPromiseRejectionTracker_(vm_, promise, reason, operation, data_);
176        }
177    }
178
179    void SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)
180    {
181        hostPromiseRejectionTracker_ = cb;
182    }
183    void SetupRegExpResultCache();
184    void SetupNumberToStringResultCache();
185    void SetupStringSplitResultCache();
186    void SetupStringToListResultCache();
187    JSHandle<JSTaggedValue> GetRegExpCache() const
188    {
189        return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&regexpCache_));
190    }
191
192    RegExpParserCache *GetRegExpParserCache() const
193    {
194        ASSERT(regExpParserCache_ != nullptr);
195        return regExpParserCache_;
196    }
197
198    void SetRegExpCache(JSTaggedValue newCache)
199    {
200        regexpCache_ = newCache;
201    }
202    uintptr_t GetExpCacheAddress()
203    {
204        return reinterpret_cast<uintptr_t>(&regexpCache_);
205    }
206
207    void SetupRegExpGlobalResult();
208
209    JSHandle<JSTaggedValue> GetRegExpGlobalResult() const
210    {
211        return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&regexpGlobal_));
212    }
213
214    void SetRegExpGlobalResult(JSTaggedValue newResult)
215    {
216        regexpGlobal_ = newResult;
217    }
218
219    WaiterListNode *GetWaiterListNode()
220    {
221        return &waiterListNode_;
222    }
223
224    void SetAllowAtomicWait(bool wait)
225    {
226        AllowAtomicWait_ = wait;
227    }
228
229    bool GetAllowAtomicWait() const
230    {
231        return AllowAtomicWait_;
232    }
233    JSHandle<JSTaggedValue> GetNumberToStringResultCache() const
234    {
235        return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&numberToStringResultCache_));
236    }
237
238    void SetNumberToStringResultCache(JSTaggedValue newCache)
239    {
240        numberToStringResultCache_ = newCache;
241    }
242
243    JSHandle<JSTaggedValue> GetStringSplitResultCache() const
244    {
245        return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&stringSplitResultCache_));
246    }
247
248    JSHandle<JSTaggedValue> GetStringToListResultCache() const
249    {
250        return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&stringToListResultCache_));
251    }
252
253    void SetStringSplitResultCache(JSTaggedValue newCache)
254    {
255        stringSplitResultCache_ = newCache;
256    }
257    JSHandle<ecmascript::JSTaggedValue> GetAndClearEcmaUncaughtException() const;
258    JSHandle<ecmascript::JSTaggedValue> GetEcmaUncaughtException() const;
259    void EnableUserUncaughtErrorHandler();
260
261    JSHandle<ConstantPool> AddOrUpdateConstpool(const JSPandaFile *jsPandaFile,
262                                                JSHandle<ConstantPool> constpool,
263                                                int32_t index = 0);
264    void AddContextConstpoolCache(const JSPandaFile *jsPandaFile,
265                                  JSHandle<ConstantPool> constpool,
266                                  int32_t index);
267
268    void UpdateConstpoolWhenDeserialAI(const std::string& fileName,
269                                       JSHandle<ConstantPool> aiCP,
270                                       int32_t index = 0);
271
272    bool HasCachedConstpool(const JSPandaFile *jsPandaFile) const;
273
274    void SetUnsharedConstpool(JSHandle<ConstantPool> sharedConstpool, JSTaggedValue unsharedConstpool);
275    void SetUnsharedConstpool(int32_t constpoolIndex, JSTaggedValue unsharedConstpool);
276
277    JSTaggedValue PUBLIC_API FindConstpool(const JSPandaFile *jsPandaFile, int32_t index);
278    // For new version instruction.
279    JSTaggedValue PUBLIC_API FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id);
280    JSTaggedValue PUBLIC_API FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool);
281    JSTaggedValue PUBLIC_API FindUnsharedConstpool(JSTaggedValue sharedConstpool);
282    void PUBLIC_API LoadProtoTransitionTable(JSTaggedValue constpool);
283    void PUBLIC_API ResetProtoTransitionTableOnConstpool(JSTaggedValue constpool);
284    JSTaggedValue FindCachedConstpoolAndLoadAiIfNeeded(const JSPandaFile *jsPandaFile, int32_t index);
285    void EraseUnusedConstpool(const JSPandaFile *jsPandaFile, int32_t index, int32_t constpoolIndex);
286    std::optional<std::reference_wrapper<CMap<int32_t, JSTaggedValue>>> FindConstpools(
287        const JSPandaFile *jsPandaFile);
288
289    JSHandle<ConstantPool> PUBLIC_API FindOrCreateConstPool(const JSPandaFile *jsPandaFile,
290                                                            panda_file::File::EntityId id);
291    void CreateAllConstpool(const JSPandaFile *jsPandaFile);
292
293    void HandleUncaughtException(JSTaggedValue exception);
294    void HandleUncaughtException();
295    JSHandle<GlobalEnv> GetGlobalEnv() const;
296    bool GlobalEnvIsHole()
297    {
298        return globalEnv_.IsHole();
299    }
300
301    JSHandle<job::MicroJobQueue> GetMicroJobQueue() const;
302
303    static void PrintJSErrorInfo(JSThread *thread, const JSHandle<JSTaggedValue> &exceptionInfo);
304    void Iterate(const RootVisitor &v, const RootRangeVisitor &rv);
305    static void MountContext(JSThread *thread);
306    static void UnmountContext(JSThread *thread);
307    void SetMicroJobQueue(job::MicroJobQueue *queue);
308    void SetGlobalEnv(GlobalEnv *global);
309    void PrintOptStat();
310
311    OptCodeProfiler *GetOptCodeProfiler() const
312    {
313        return optCodeProfiler_;
314    }
315
316    TypedOpProfiler *GetTypdOpProfiler() const
317    {
318        return typedOpProfiler_;
319    }
320
321    ModuleLogger *GetModuleLogger() const
322    {
323        return moduleLogger_;
324    }
325
326    void SetModuleLogger(ModuleLogger *moduleLogger)
327    {
328        moduleLogger_ = moduleLogger;
329    }
330
331    void SetDefaultLocale(const std::string& locale)
332    {
333        defaultLocale_ = locale;
334    }
335
336    const std::string& GetDefaultLocale() const
337    {
338        return defaultLocale_;
339    }
340
341    void InitializeDefaultLocale()
342    {
343        defaultLocale_ = "";
344    }
345
346    void ClearDefaultLocale()
347    {
348        defaultLocale_.clear();
349    }
350
351    void SetDefaultCompareStringsOption(const CompareStringsOption csOption)
352    {
353        defaultComapreStringsOption_ = csOption;
354    }
355
356    const std::optional<CompareStringsOption> GetDefaultCompareStringsOption() const
357    {
358        return defaultComapreStringsOption_;
359    }
360
361    void InitializeDefaultCompareStringsOption()
362    {
363        defaultComapreStringsOption_ = std::nullopt;
364    }
365
366    void ClearDefaultComapreStringsOption()
367    {
368        defaultComapreStringsOption_ = std::nullopt;
369    }
370
371    FunctionProtoTransitionTable *GetFunctionProtoTransitionTable() const
372    {
373        return functionProtoTransitionTable_;
374    }
375
376    // For icu objects cache
377    void SetIcuFormatterToCache(IcuFormatterType type, const std::string &locale, void *icuObj,
378                                NativePointerCallback deleteEntry = nullptr)
379    {
380        EcmaContext::IcuFormatter icuFormatter = IcuFormatter(locale, icuObj, deleteEntry);
381        icuObjCache_[static_cast<int>(type)] = icuFormatter;
382    }
383
384    ARK_INLINE void *GetIcuFormatterFromCache(IcuFormatterType type, std::string &locale)
385    {
386        auto &icuFormatter = icuObjCache_[static_cast<int>(type)];
387        if (icuFormatter.locale == locale) {
388            return icuFormatter.icuObj;
389        }
390        return nullptr;
391    }
392
393    void ClearIcuCache(JSThread *thread);
394
395    EcmaRuntimeStat *GetRuntimeStat() const
396    {
397        return runtimeStat_;
398    }
399
400    void SetRuntimeStatEnable(bool flag);
401    void InitializeEcmaScriptRunStat();
402    void DumpAOTInfo() const DUMP_API_ATTR;
403
404    JSTaggedValue ExecuteAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp,
405                             bool needPushArgv);
406    void LoadStubFile();
407
408    JSTaggedType *GetHandleScopeStorageNext() const
409    {
410        return handleScopeStorageNext_;
411    }
412
413    void SetHandleScopeStorageNext(JSTaggedType *value)
414    {
415        handleScopeStorageNext_ = value;
416    }
417
418    JSTaggedType *GetHandleScopeStorageEnd() const
419    {
420        return handleScopeStorageEnd_;
421    }
422
423    void SetHandleScopeStorageEnd(JSTaggedType *value)
424    {
425        handleScopeStorageEnd_ = value;
426    }
427
428    int GetCurrentHandleStorageIndex() const
429    {
430        return currentHandleStorageIndex_;
431    }
432
433#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
434    void HandleScopeCountAdd()
435    {
436        handleScopeCount_++;
437    }
438
439    void HandleScopeCountDec()
440    {
441        handleScopeCount_--;
442    }
443
444    void PrimitiveScopeCountAdd()
445    {
446        primitiveScopeCount_++;
447    }
448
449    void PrimitiveScopeCountDec()
450    {
451        primitiveScopeCount_--;
452    }
453#endif
454
455    void SetLastHandleScope(EcmaHandleScope *scope)
456    {
457        lastHandleScope_ = scope;
458    }
459
460    EcmaHandleScope *GetLastHandleScope() const
461    {
462        return lastHandleScope_;
463    }
464
465    JSTaggedType *GetPrimitiveScopeStorageNext() const
466    {
467        return primitiveScopeStorageNext_;
468    }
469
470    void SetPrimitiveScopeStorageNext(JSTaggedType *value)
471    {
472        primitiveScopeStorageNext_ = value;
473    }
474
475    JSTaggedType *GetPrimitiveScopeStorageEnd() const
476    {
477        return primitiveScopeStorageEnd_;
478    }
479
480    void SetPrimitiveScopeStorageEnd(JSTaggedType *value)
481    {
482        primitiveScopeStorageEnd_ = value;
483    }
484
485    int GetCurrentPrimitiveStorageIndex() const
486    {
487        return currentPrimitiveStorageIndex_;
488    }
489
490    void SetLastPrimitiveScope(EcmaHandleScope *scope)
491    {
492        lastPrimitiveScope_ = scope;
493    }
494
495    EcmaHandleScope *GetLastPrimitiveScope() const
496    {
497        return lastPrimitiveScope_;
498    }
499
500    size_t IterateHandle(const RootRangeVisitor &rangeVisitor);
501    uintptr_t *ExpandHandleStorage();
502    void ShrinkHandleStorage(int prevIndex);
503    uintptr_t *ExpandPrimitiveStorage();
504    void ShrinkPrimitiveStorage(int prevIndex);
505
506    JSTaggedType *GetCurrentFrame() const
507    {
508        return currentFrame_;
509    }
510
511    JSTaggedType *GetLeaveFrame() const
512    {
513        return leaveFrame_;
514    }
515
516    JSTaggedType *GetLastFp() const
517    {
518        return lastFp_;
519    }
520
521    void SetFramePointers(JSTaggedType *currentFrame, JSTaggedType *leaveFrame, JSTaggedType *lastFp)
522    {
523        currentFrame_ = currentFrame;
524        leaveFrame_ = leaveFrame;
525        lastFp_ = lastFp;
526    }
527    void SetFrameBase(JSTaggedType *frameBase)
528    {
529        frameBase_ = frameBase;
530    }
531    JSTaggedType *GetFrameBase() const
532    {
533        return frameBase_;
534    }
535
536    void SetStackStart(uint64_t stackStart)
537    {
538        stackStart_ = stackStart;
539    }
540    uint64_t GetStackStart() const
541    {
542        return stackStart_;
543    }
544    void SetStackLimit(uint64_t stackLimit)
545    {
546        stackLimit_ = stackLimit;
547    }
548    uint64_t GetStackLimit() const
549    {
550        return stackLimit_;
551    }
552
553    PropertiesCache *GetPropertiesCache() const
554    {
555        return propertiesCache_;
556    }
557    void ClearBufferData();
558    const GlobalEnvConstants *GlobalConstants() const
559    {
560        return &globalConst_;
561    }
562
563    void AddPatchModule(const CString &recordName, const JSHandle<JSTaggedValue> moduleRecord)
564    {
565        cachedPatchModules_.emplace(recordName, moduleRecord);
566    }
567    JSHandle<JSTaggedValue> FindPatchModule(const CString &recordName) const
568    {
569        auto iter = cachedPatchModules_.find(recordName);
570        if (iter != cachedPatchModules_.end()) {
571            return iter->second;
572        }
573        return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole());
574    }
575    void ClearPatchModules()
576    {
577        GlobalHandleCollection gloalHandleCollection(thread_);
578        for (auto &item : cachedPatchModules_) {
579            gloalHandleCollection.Dispose(item.second);
580        }
581        cachedPatchModules_.clear();
582    }
583
584    StageOfHotReload GetStageOfHotReload() const
585    {
586        return stageOfHotReload_;
587    }
588    void SetStageOfHotReload(StageOfHotReload stageOfHotReload)
589    {
590        stageOfHotReload_ = stageOfHotReload;
591    }
592
593    StageOfColdReload GetStageOfColdReload() const
594    {
595        return stageOfColdReload_;
596    }
597    void SetStageOfColdReload(StageOfColdReload stageOfColdReload)
598    {
599        stageOfColdReload_ = stageOfColdReload;
600    }
601
602    bool JoinStackPushFastPath(JSHandle<JSTaggedValue> receiver);
603    bool JoinStackPush(JSHandle<JSTaggedValue> receiver);
604    void JoinStackPopFastPath(JSHandle<JSTaggedValue> receiver);
605    void JoinStackPop(JSHandle<JSTaggedValue> receiver);
606
607    void SetJsonStringifyCache(size_t index, CVector<std::pair<CString, int>> &value)
608    {
609        stringifyCache_[index] = value;
610    }
611
612    CVector<std::pair<CString, int>> GetJsonStringifyCache(size_t index)
613    {
614        return stringifyCache_[index];
615    }
616
617    bool IsAotEntry()
618    {
619        return isAotEntry_;
620    }
621
622    std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr,
623                                                                                        bool isDeopt) const;
624
625    void AddSustainingJSHandle(SustainingJSHandle*);
626    void RemoveSustainingJSHandle(SustainingJSHandle*);
627    void ClearKeptObjects();
628    void AddToKeptObjects(JSHandle<JSTaggedValue> value);
629    inline bool HasKeptObjects() const
630    {
631        return hasKeptObjects_;
632    }
633
634    void ClearCachedConstantPool()
635    {
636        cachedSharedConstpools_.clear();
637    }
638
639private:
640    void CJSExecution(JSHandle<JSFunction> &func, JSHandle<JSTaggedValue> &thisArg,
641                      const JSPandaFile *jsPandaFile, std::string_view entryPoint);
642    JSTaggedValue InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc, JSHandle<JSTaggedValue> &thisArg,
643                                          const JSPandaFile *jsPandaFile, std::string_view entryPoint,
644                                          CJSInfo *cjsInfo = nullptr);
645    Expected<JSTaggedValue, bool> InvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile, std::string_view entryPoint,
646                                                       bool executeFromJob = false);
647    Expected<JSTaggedValue, bool> InvokeEcmaEntrypointForHotReload(
648        const JSPandaFile *jsPandaFile, std::string_view entryPoint, bool executeFromJob);
649    Expected<JSTaggedValue, bool> CommonInvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile,
650        std::string_view entryPoint, JSHandle<JSFunction> &func, bool executeFromJob);
651    bool LoadAOTFilesInternal(const std::string& aotFileName);
652    bool LoadAOTFiles(const std::string &aotFileName);
653#if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
654    bool LoadAOTFiles(const std::string &aotFileName,
655                      std::function<bool(std::string fileName, uint8_t **buff, size_t *buffSize)> cb);
656#endif
657    void RelocateConstantString(const JSPandaFile *jsPandaFile);
658    JSTaggedValue FindConstpoolFromContextCache(const JSPandaFile *jsPandaFile, int32_t index);
659
660    void CheckUnsharedConstpoolArrayLimit(int32_t index)
661    {
662        if (index >= UNSHARED_CONSTANTPOOL_COUNT) {
663            LOG_ECMA(FATAL) << "the unshared constpool array need to expanding capacity, index :" << index;
664            UNREACHABLE();
665        }
666    }
667
668    NO_MOVE_SEMANTIC(EcmaContext);
669    NO_COPY_SEMANTIC(EcmaContext);
670
671    PropertiesCache *propertiesCache_ {nullptr};
672    JSThread *thread_ {nullptr};
673    EcmaVM *vm_ {nullptr};
674
675    bool isUncaughtExceptionRegistered_ {false};
676    bool initialized_ {false};
677    std::atomic<bool> isProcessingPendingJob_ {false};
678    ObjectFactory *factory_ {nullptr};
679
680    // VM execution states.
681    RegExpParserCache *regExpParserCache_ {nullptr};
682    JSTaggedValue numberToStringResultCache_ {JSTaggedValue::Hole()};
683    JSTaggedValue stringSplitResultCache_ {JSTaggedValue::Hole()};
684    JSTaggedValue stringToListResultCache_ {JSTaggedValue::Hole()};
685    JSTaggedValue globalEnv_ {JSTaggedValue::Hole()};
686    JSTaggedValue pointerToIndexDictionary_ {JSTaggedValue::Hole()};
687    JSTaggedValue regexpCache_ {JSTaggedValue::Hole()};
688    JSTaggedValue regexpGlobal_ {JSTaggedValue::Hole()};
689    JSTaggedValue microJobQueue_ {JSTaggedValue::Hole()};
690    EcmaRuntimeStat *runtimeStat_ {nullptr};
691
692    CMap<const JSPandaFile *, CMap<int32_t, JSTaggedValue>> cachedSharedConstpools_ {};
693    std::array<JSTaggedValue, UNSHARED_CONSTANTPOOL_COUNT> unsharedConstpools_ {};
694    static constexpr int32_t SHARED_CONSTPOOL_KEY_NOT_FOUND = INT32_MAX; // INT32_MAX :invalid value.
695
696    // for HotReload of module.
697    CMap<CString, JSHandle<JSTaggedValue>> cachedPatchModules_ {};
698    StageOfHotReload stageOfHotReload_ = StageOfHotReload::INITIALIZE_STAGE_OF_HOTRELOAD;
699    StageOfColdReload stageOfColdReload_ = StageOfColdReload::NOT_COLD_RELOAD;
700
701    // VM resources.
702    ModuleManager *moduleManager_ {nullptr};
703    kungfu::PGOTypeManager *ptManager_ {nullptr};
704    AOTFileManager *aotFileManager_ {nullptr};
705    AbcBufferCache *abcBufferCache_ {nullptr};
706
707    // for recording the transition of function prototype
708    FunctionProtoTransitionTable *functionProtoTransitionTable_ {nullptr};
709
710    // atomics
711    bool AllowAtomicWait_ {true};
712    WaiterListNode waiterListNode_;
713
714    // Registered Callbacks
715    PromiseRejectCallback promiseRejectCallback_ {nullptr};
716    HostPromiseRejectionTracker hostPromiseRejectionTracker_ {nullptr};
717    void* data_{nullptr};
718
719    // opt code Profiler
720    OptCodeProfiler *optCodeProfiler_ {nullptr};
721
722    // opt code loop hoist
723    TypedOpProfiler *typedOpProfiler_ {nullptr};
724
725    ModuleLogger *moduleLogger_ {nullptr};
726
727    std::string defaultLocale_;
728    std::optional<CompareStringsOption> defaultComapreStringsOption_;
729
730    // For icu objects cache
731    struct IcuFormatter {
732        std::string locale;
733        void *icuObj {nullptr};
734        NativePointerCallback deleteEntry {nullptr};
735
736        IcuFormatter() = default;
737        IcuFormatter(const std::string &locale, void *icuObj, NativePointerCallback deleteEntry = nullptr)
738            : locale(locale), icuObj(icuObj), deleteEntry(deleteEntry) {}
739    };
740    IcuFormatter icuObjCache_[static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT)];
741    // Handlescope
742    static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10;
743    static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2;
744    static constexpr int32_t MIN_HANDLE_STORAGE_SIZE = 2;
745    JSTaggedType *handleScopeStorageNext_ {nullptr};
746    JSTaggedType *handleScopeStorageEnd_ {nullptr};
747    std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> handleStorageNodes_ {};
748    int32_t currentHandleStorageIndex_ {-1};
749#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
750    int32_t handleScopeCount_ {0};
751    int32_t primitiveScopeCount_ {0};
752#endif
753    EcmaHandleScope *lastHandleScope_ {nullptr};
754    // PrimitveScope
755    static constexpr int32_t MIN_PRIMITIVE_STORAGE_SIZE = 2;
756    JSTaggedType *primitiveScopeStorageNext_ {nullptr};
757    JSTaggedType *primitiveScopeStorageEnd_ {nullptr};
758    std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> primitiveStorageNodes_ {};
759    int32_t currentPrimitiveStorageIndex_ {-1};
760    EcmaHandleScope *lastPrimitiveScope_ {nullptr};
761
762    // Frame pointer
763    JSTaggedType *currentFrame_ {nullptr};
764    JSTaggedType *leaveFrame_ {nullptr};
765    JSTaggedType *lastFp_ {nullptr};
766    JSTaggedType *frameBase_ {nullptr};
767    uint64_t stackStart_ {0};
768    uint64_t stackLimit_ {0};
769    GlobalEnvConstants globalConst_;
770    // Join Stack
771    static constexpr uint32_t MIN_JOIN_STACK_SIZE = 2;
772    CVector<JSTaggedValue> joinStack_ {JSTaggedValue::Hole(), JSTaggedValue::Hole()};
773    // json stringify cache
774    static constexpr uint32_t STRINGIFY_CACHE_SIZE = 64;
775    std::array<CVector<std::pair<CString, int>>, STRINGIFY_CACHE_SIZE> stringifyCache_ {};
776    bool isAotEntry_ { false };
777
778    // SustainingJSHandleList for jit compile hold ref
779    SustainingJSHandleList *sustainingJSHandleList_ {nullptr};
780
781    bool hasKeptObjects_ {false};
782
783    friend class EcmaHandleScope;
784    friend class JSPandaFileExecutor;
785    friend class ObjectFactory;
786    friend class panda::JSNApi;
787    friend class AOTFileManager;
788    friend class GlobalIndexMap;
789};
790}  // namespace ecmascript
791}  // namespace panda
792#endif // ECMASCRIPT_ECMA_CONTEXT_H
793