• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 EcmaRuntimeStat;
42 class RegExpParserCache;
43 class JSPandaFileManager;
44 class JSPandaFile;
45 class ConstantPool;
46 class JSPromise;
47 class RegExpExecResultCache;
48 class EcmaHandleScope;
49 class GlobalIndexMap;
50 class SustainingJSHandleList;
51 class SustainingJSHandle;
52 enum class PromiseRejectionEvent : uint8_t;
53 enum class CompareStringsOption : uint8_t;
54 
55 template<typename T>
56 class JSHandle;
57 class JSThread;
58 class JSFunction;
59 class JSPromise;
60 class JSTaggedValue;
61 class EcmaVM;
62 class ModuleManager;
63 class AOTFileManager;
64 class QuickFixManager;
65 class OptCodeProfiler;
66 class TypedOpProfiler;
67 class AbcBufferCache;
68 struct CJSInfo;
69 class FunctionProtoTransitionTable;
70 class ModuleLogger;
71 
72 namespace job {
73 class MicroJobQueue;
74 }  // namespace job
75 namespace tooling {
76 class JsDebuggerManager;
77 }  // namespace tooling
78 namespace kungfu {
79 class PGOTypeManager;
80 } // namespace kungfu
81 
82 enum 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 
91 using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
92                                              const JSHandle<JSPromise> promise,
93                                              const JSHandle<JSTaggedValue> reason,
94                                              PromiseRejectionEvent operation,
95                                              void* data);
96 using PromiseRejectCallback = void (*)(void* info);
97 #if defined(CROSS_PLATFORM) && defined(ANDROID_PLATFORM)
98 using JsAotReaderCallback = std::function<bool(std::string fileName, uint8_t **buff, size_t *buffSize)>;
99 #endif
100 class EcmaContext {
101 public:
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 
GetEcmaVM()111     EcmaVM *GetEcmaVM() const
112     {
113         return vm_;
114     }
115 
116     bool Initialize();
117 
IsExecutingPendingJob()118     bool IsExecutingPendingJob() const
119     {
120         return isProcessingPendingJob_.load();
121     }
122 
123     bool HasPendingJob();
124 
125     bool ExecutePromisePendingJob();
126 
ConstCast(const EcmaContext * context)127     static EcmaContext *ConstCast(const EcmaContext *context)
128     {
129         return const_cast<EcmaContext *>(context);
130     }
131 
IsInitialized()132     bool IsInitialized() const
133     {
134         return initialized_;
135     }
136 
GetModuleManager()137     ModuleManager *GetModuleManager() const
138     {
139         return moduleManager_;
140     }
141 
GetAbcBufferCache()142     AbcBufferCache *GetAbcBufferCache() const
143     {
144         return abcBufferCache_;
145     }
146 
GetPTManager()147     kungfu::PGOTypeManager *GetPTManager() const
148     {
149         return ptManager_;
150     }
151 
GetJSThread()152     ARK_INLINE JSThread *GetJSThread() const
153     {
154         return thread_;
155     }
GetPromiseRejectCallback()156     PromiseRejectCallback GetPromiseRejectCallback() const
157     {
158         return promiseRejectCallback_;
159     }
160 
SetPromiseRejectCallback(PromiseRejectCallback cb)161     void SetPromiseRejectCallback(PromiseRejectCallback cb)
162     {
163         promiseRejectCallback_ = cb;
164     }
165 
SetData(void * data)166     void SetData(void* data)
167     {
168         data_ = data;
169     }
170 
PromiseRejectionTracker(const JSHandle<JSPromise> & promise,const JSHandle<JSTaggedValue> & reason,PromiseRejectionEvent operation)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 
SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)179     void SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)
180     {
181         hostPromiseRejectionTracker_ = cb;
182     }
183     void SetupRegExpResultCache();
184     void SetupNumberToStringResultCache();
185     void SetupStringSplitResultCache();
186     void SetupStringToListResultCache();
GetRegExpCache()187     JSHandle<JSTaggedValue> GetRegExpCache() const
188     {
189         return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&regexpCache_));
190     }
191 
GetRegExpParserCache()192     RegExpParserCache *GetRegExpParserCache() const
193     {
194         ASSERT(regExpParserCache_ != nullptr);
195         return regExpParserCache_;
196     }
197 
SetRegExpCache(JSTaggedValue newCache)198     void SetRegExpCache(JSTaggedValue newCache)
199     {
200         regexpCache_ = newCache;
201     }
GetExpCacheAddress()202     uintptr_t GetExpCacheAddress()
203     {
204         return reinterpret_cast<uintptr_t>(&regexpCache_);
205     }
206 
207     void SetupRegExpGlobalResult();
208 
GetRegExpGlobalResult()209     JSHandle<JSTaggedValue> GetRegExpGlobalResult() const
210     {
211         return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&regexpGlobal_));
212     }
213 
SetRegExpGlobalResult(JSTaggedValue newResult)214     void SetRegExpGlobalResult(JSTaggedValue newResult)
215     {
216         regexpGlobal_ = newResult;
217     }
218 
GetWaiterListNode()219     WaiterListNode *GetWaiterListNode()
220     {
221         return &waiterListNode_;
222     }
223 
SetAllowAtomicWait(bool wait)224     void SetAllowAtomicWait(bool wait)
225     {
226         AllowAtomicWait_ = wait;
227     }
228 
GetAllowAtomicWait()229     bool GetAllowAtomicWait() const
230     {
231         return AllowAtomicWait_;
232     }
GetNumberToStringResultCache()233     JSHandle<JSTaggedValue> GetNumberToStringResultCache() const
234     {
235         return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&numberToStringResultCache_));
236     }
237 
SetNumberToStringResultCache(JSTaggedValue newCache)238     void SetNumberToStringResultCache(JSTaggedValue newCache)
239     {
240         numberToStringResultCache_ = newCache;
241     }
242 
GetStringSplitResultCache()243     JSHandle<JSTaggedValue> GetStringSplitResultCache() const
244     {
245         return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&stringSplitResultCache_));
246     }
247 
GetStringToListResultCache()248     JSHandle<JSTaggedValue> GetStringToListResultCache() const
249     {
250         return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(&stringToListResultCache_));
251     }
252 
SetStringSplitResultCache(JSTaggedValue newCache)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;
GlobalEnvIsHole()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 
GetOptCodeProfiler()311     OptCodeProfiler *GetOptCodeProfiler() const
312     {
313         return optCodeProfiler_;
314     }
315 
GetTypdOpProfiler()316     TypedOpProfiler *GetTypdOpProfiler() const
317     {
318         return typedOpProfiler_;
319     }
320 
GetModuleLogger()321     ModuleLogger *GetModuleLogger() const
322     {
323         return moduleLogger_;
324     }
325 
SetModuleLogger(ModuleLogger * moduleLogger)326     void SetModuleLogger(ModuleLogger *moduleLogger)
327     {
328         moduleLogger_ = moduleLogger;
329     }
330 
SetDefaultLocale(const std::string & locale)331     void SetDefaultLocale(const std::string& locale)
332     {
333         defaultLocale_ = locale;
334     }
335 
GetDefaultLocale()336     const std::string& GetDefaultLocale() const
337     {
338         return defaultLocale_;
339     }
340 
InitializeDefaultLocale()341     void InitializeDefaultLocale()
342     {
343         defaultLocale_ = "";
344     }
345 
ClearDefaultLocale()346     void ClearDefaultLocale()
347     {
348         defaultLocale_.clear();
349     }
350 
SetDefaultCompareStringsOption(const CompareStringsOption csOption)351     void SetDefaultCompareStringsOption(const CompareStringsOption csOption)
352     {
353         defaultComapreStringsOption_ = csOption;
354     }
355 
GetDefaultCompareStringsOption()356     const std::optional<CompareStringsOption> GetDefaultCompareStringsOption() const
357     {
358         return defaultComapreStringsOption_;
359     }
360 
InitializeDefaultCompareStringsOption()361     void InitializeDefaultCompareStringsOption()
362     {
363         defaultComapreStringsOption_ = std::nullopt;
364     }
365 
ClearDefaultComapreStringsOption()366     void ClearDefaultComapreStringsOption()
367     {
368         defaultComapreStringsOption_ = std::nullopt;
369     }
370 
GetFunctionProtoTransitionTable()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 
GetIcuFormatterFromCache(IcuFormatterType type,std::string & locale)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 
GetRuntimeStat()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 
GetHandleScopeStorageNext()408     JSTaggedType *GetHandleScopeStorageNext() const
409     {
410         return handleScopeStorageNext_;
411     }
412 
SetHandleScopeStorageNext(JSTaggedType * value)413     void SetHandleScopeStorageNext(JSTaggedType *value)
414     {
415         handleScopeStorageNext_ = value;
416     }
417 
GetHandleScopeStorageEnd()418     JSTaggedType *GetHandleScopeStorageEnd() const
419     {
420         return handleScopeStorageEnd_;
421     }
422 
SetHandleScopeStorageEnd(JSTaggedType * value)423     void SetHandleScopeStorageEnd(JSTaggedType *value)
424     {
425         handleScopeStorageEnd_ = value;
426     }
427 
GetCurrentHandleStorageIndex()428     int GetCurrentHandleStorageIndex() const
429     {
430         return currentHandleStorageIndex_;
431     }
432 
433 #ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
HandleScopeCountAdd()434     void HandleScopeCountAdd()
435     {
436         handleScopeCount_++;
437     }
438 
HandleScopeCountDec()439     void HandleScopeCountDec()
440     {
441         handleScopeCount_--;
442     }
443 
PrimitiveScopeCountAdd()444     void PrimitiveScopeCountAdd()
445     {
446         primitiveScopeCount_++;
447     }
448 
PrimitiveScopeCountDec()449     void PrimitiveScopeCountDec()
450     {
451         primitiveScopeCount_--;
452     }
453 #endif
454 
SetLastHandleScope(EcmaHandleScope * scope)455     void SetLastHandleScope(EcmaHandleScope *scope)
456     {
457         lastHandleScope_ = scope;
458     }
459 
GetLastHandleScope()460     EcmaHandleScope *GetLastHandleScope() const
461     {
462         return lastHandleScope_;
463     }
464 
GetPrimitiveScopeStorageNext()465     JSTaggedType *GetPrimitiveScopeStorageNext() const
466     {
467         return primitiveScopeStorageNext_;
468     }
469 
SetPrimitiveScopeStorageNext(JSTaggedType * value)470     void SetPrimitiveScopeStorageNext(JSTaggedType *value)
471     {
472         primitiveScopeStorageNext_ = value;
473     }
474 
GetPrimitiveScopeStorageEnd()475     JSTaggedType *GetPrimitiveScopeStorageEnd() const
476     {
477         return primitiveScopeStorageEnd_;
478     }
479 
SetPrimitiveScopeStorageEnd(JSTaggedType * value)480     void SetPrimitiveScopeStorageEnd(JSTaggedType *value)
481     {
482         primitiveScopeStorageEnd_ = value;
483     }
484 
GetCurrentPrimitiveStorageIndex()485     int GetCurrentPrimitiveStorageIndex() const
486     {
487         return currentPrimitiveStorageIndex_;
488     }
489 
SetLastPrimitiveScope(EcmaHandleScope * scope)490     void SetLastPrimitiveScope(EcmaHandleScope *scope)
491     {
492         lastPrimitiveScope_ = scope;
493     }
494 
GetLastPrimitiveScope()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 
GetCurrentFrame()506     JSTaggedType *GetCurrentFrame() const
507     {
508         return currentFrame_;
509     }
510 
GetLeaveFrame()511     JSTaggedType *GetLeaveFrame() const
512     {
513         return leaveFrame_;
514     }
515 
GetLastFp()516     JSTaggedType *GetLastFp() const
517     {
518         return lastFp_;
519     }
520 
SetFramePointers(JSTaggedType * currentFrame,JSTaggedType * leaveFrame,JSTaggedType * lastFp)521     void SetFramePointers(JSTaggedType *currentFrame, JSTaggedType *leaveFrame, JSTaggedType *lastFp)
522     {
523         currentFrame_ = currentFrame;
524         leaveFrame_ = leaveFrame;
525         lastFp_ = lastFp;
526     }
SetFrameBase(JSTaggedType * frameBase)527     void SetFrameBase(JSTaggedType *frameBase)
528     {
529         frameBase_ = frameBase;
530     }
GetFrameBase()531     JSTaggedType *GetFrameBase() const
532     {
533         return frameBase_;
534     }
535 
SetStackStart(uint64_t stackStart)536     void SetStackStart(uint64_t stackStart)
537     {
538         stackStart_ = stackStart;
539     }
GetStackStart()540     uint64_t GetStackStart() const
541     {
542         return stackStart_;
543     }
SetStackLimit(uint64_t stackLimit)544     void SetStackLimit(uint64_t stackLimit)
545     {
546         stackLimit_ = stackLimit;
547     }
GetStackLimit()548     uint64_t GetStackLimit() const
549     {
550         return stackLimit_;
551     }
552 
GetPropertiesCache()553     PropertiesCache *GetPropertiesCache() const
554     {
555         return propertiesCache_;
556     }
557     void ClearBufferData();
GlobalConstants()558     const GlobalEnvConstants *GlobalConstants() const
559     {
560         return &globalConst_;
561     }
562 
AddPatchModule(const CString & recordName,const JSHandle<JSTaggedValue> moduleRecord)563     void AddPatchModule(const CString &recordName, const JSHandle<JSTaggedValue> moduleRecord)
564     {
565         cachedPatchModules_.emplace(recordName, moduleRecord);
566     }
FindPatchModule(const CString & recordName)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     }
ClearPatchModules()575     void ClearPatchModules()
576     {
577         GlobalHandleCollection gloalHandleCollection(thread_);
578         for (auto &item : cachedPatchModules_) {
579             gloalHandleCollection.Dispose(item.second);
580         }
581         cachedPatchModules_.clear();
582     }
583 
GetStageOfHotReload()584     StageOfHotReload GetStageOfHotReload() const
585     {
586         return stageOfHotReload_;
587     }
SetStageOfHotReload(StageOfHotReload stageOfHotReload)588     void SetStageOfHotReload(StageOfHotReload stageOfHotReload)
589     {
590         stageOfHotReload_ = stageOfHotReload;
591     }
592 
GetStageOfColdReload()593     StageOfColdReload GetStageOfColdReload() const
594     {
595         return stageOfColdReload_;
596     }
SetStageOfColdReload(StageOfColdReload stageOfColdReload)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 
SetJsonStringifyCache(size_t index,CVector<std::pair<CString,int>> & value)607     void SetJsonStringifyCache(size_t index, CVector<std::pair<CString, int>> &value)
608     {
609         stringifyCache_[index] = value;
610     }
611 
GetJsonStringifyCache(size_t index)612     CVector<std::pair<CString, int>> GetJsonStringifyCache(size_t index)
613     {
614         return stringifyCache_[index];
615     }
616 
IsAotEntry()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);
HasKeptObjects()629     inline bool HasKeptObjects() const
630     {
631         return hasKeptObjects_;
632     }
633 
ClearCachedConstantPool()634     void ClearCachedConstantPool()
635     {
636         cachedSharedConstpools_.clear();
637     }
638 
639 private:
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 
CheckUnsharedConstpoolArrayLimit(int32_t index)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)
localeIcuFormatter738             : 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