* Copyright (c) 2021-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_ECMA_VM_H
#define ECMASCRIPT_ECMA_VM_H
#include "ecmascript/cross_vm/ecma_vm_hybrid.h"
#include <atomic>
#include <ctime>
#include <functional>
#include <mutex>
#ifdef PANDA_JS_ETS_HYBRID_MODE
#include "ecmascript/cross_vm/cross_vm_operator.h"
#endif
#include "ecmascript/base/config.h"
#include "ecmascript/builtins/builtins_method_index.h"
#include "ecmascript/global_env_constants.h"
#include "ecmascript/global_handle_collection.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/mem/c_containers.h"
#include "ecmascript/mem/c_string.h"
#include "ecmascript/mem/gc_key_stats.h"
#include "ecmascript/mem/gc_stats.h"
#include "ecmascript/mem/heap_region_allocator.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/napi/include/dfx_jsnapi.h"
#include "ecmascript/patch/patch_loader.h"
#include "ecmascript/stackmap/ark_stackmap.h"
#include "ecmascript/napi/include/jsnapi_expo.h"
#include "ecmascript/platform/mutex.h"
#include "ecmascript/waiter_list.h"
#include "bytecode_instruction-inl.h"
namespace panda {
class JSNApi;
struct HmsMap;
namespace panda_file {
class File;
}
namespace ecmascript {
class GlobalEnv;
class ObjectFactory;
class RegExpParserCache;
class EcmaRuntimeStat;
class Heap;
class HeapTracker;
class JSNativePointer;
class Program;
class GCStats;
class GCKeyStats;
class CpuProfiler;
class Tracing;
class AsyncStackTrace;
class AsyncStackTraceManager;
class RegExpParserCache;
class JSPromise;
enum class PromiseRejectionEvent : uint8_t;
enum class Concurrent { YES, NO };
class JSPandaFileManager;
class JSPandaFile;
class EcmaStringTable;
class SnapshotEnv;
class SnapshotSerialize;
class SnapshotProcessor;
class JSThread;
namespace pgo {
class PGOProfiler;
}
class OptCodeProfiler;
class TypedOpProfiler;
class FunctionProtoTransitionTable;
struct CJSInfo;
namespace kungfu {
class PGOTypeManager;
}
using PGOProfiler = pgo::PGOProfiler;
#if !WIN_OR_MAC_OR_IOS_PLATFORM
class HeapProfilerInterface;
class HeapProfiler;
class HybridHeapProfiler;
#endif
namespace job {
class MicroJobQueue;
}
namespace tooling {
class JsDebuggerManager;
}
template<typename T>
class JSHandle;
class JSArrayBuffer;
class JSFunction;
class SourceTextModule;
class Program;
class AOTFileManager;
class SlowRuntimeStub;
class RequireManager;
class QuickFixManager;
class ConstantPool;
class FunctionCallTimer;
class EcmaStringTable;
class JSObjectResizingStrategy;
class Jit;
class JitThread;
class AbcBufferCache;
class SustainingJSHandle;
class SustainingJSHandleList;
struct CJSInfo;
enum class CompareStringsOption : uint8_t;
using NativePtrGetter = void* (*)(void* info);
using SourceMapCallback = std::function<std::string(const std::string& rawStack)>;
using SourceMapTranslateCallback = std::function<bool(std::string& url, int& line, int& column,
std::string &packageName)>;
using ResolveBufferCallback =
std::function<bool(std::string dirPath, uint8_t **buff, size_t *buffSize, std::string &errorMsg)>;
using TimerCallbackFunc = void (*)(void *data);
using TimerTaskCallback = void* (*)(EcmaVM *vm, void *data, TimerCallbackFunc func, uint64_t timeout, bool repeat);
using CancelTimerCallback = void (*)(void *timerCallbackInfo);
using UnloadNativeModuleCallback = std::function<bool(const std::string &moduleKey)>;
using RequestAotCallback =
std::function<int32_t(const std::string &bundleName, const std::string &moduleName, int32_t triggerMode)>;
using SearchHapPathCallBack = std::function<bool(const std::string moduleName, std::string &hapPath)>;
using DeviceDisconnectCallback = std::function<bool()>;
using UncatchableErrorHandler = std::function<void(panda::TryCatch&)>;
using StopPreLoadSoCallback = std::function<void()>;
using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
const JSHandle<JSPromise> promise,
const JSHandle<JSTaggedValue> reason,
PromiseRejectionEvent operation,
void* data);
using PromiseRejectCallback = void (*)(void* info);
using ExtraJSCrashMessageCallback = std::function<std::string (const EcmaVM*)>;
using NativeReferenceDataCallbackGetter = void* (*)(void* ref);
template <typename Value>
using ForEachCallback = std::function<void(int32_t index, Value value, size_t total)>;
using namespace panda;
enum class IcuFormatterType: uint8_t {
SIMPLE_DATE_FORMAT_DEFAULT,
SIMPLE_DATE_FORMAT_DATE,
SIMPLE_DATE_FORMAT_TIME,
NUMBER_FORMATTER,
COLLATOR,
ICU_FORMATTER_TYPE_COUNT
};
class IntlCache {
public:
IntlCache() = default;
void SetDefaultLocale(const std::string& locale)
{
defaultLocale_ = locale;
}
const std::string& GetDefaultLocale() const
{
return defaultLocale_;
}
void SetDefaultCompareStringsOption(const CompareStringsOption csOption)
{
defaultCompareStringsOption_ = csOption;
}
std::optional<CompareStringsOption> GetDefaultCompareStringsOption() const
{
return defaultCompareStringsOption_;
}
void SetIcuFormatterToCache(IcuFormatterType type, const std::string& locale, void* icuObj,
NativePointerCallback deleteEntry = nullptr)
{
icuObjCache_[static_cast<int>(type)] = IcuFormatter(locale, icuObj, deleteEntry);
}
void* GetIcuFormatterFromCache(IcuFormatterType type, const std::string& locale) const
{
const auto& icuFormatter = icuObjCache_[static_cast<int>(type)];
return icuFormatter.locale == locale ? icuFormatter.icuObj : nullptr;
}
void ClearIcuCache(void* vmPtr)
{
for (uint32_t i = 0; i < static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT); ++i) {
auto& icuFormatter = icuObjCache_[i];
if (icuFormatter.deleteEntry != nullptr) {
icuFormatter.deleteEntry(nullptr, icuFormatter.icuObj, vmPtr);
}
}
}
private:
class IcuFormatter {
public:
std::string locale;
void* icuObj {nullptr};
NativePointerCallback deleteEntry {nullptr};
IcuFormatter() = default;
IcuFormatter(const std::string& locale, void* icuObj, NativePointerCallback deleteEntry = nullptr)
: locale(locale), icuObj(icuObj), deleteEntry(deleteEntry) {}
};
std::string defaultLocale_;
std::optional<CompareStringsOption> defaultCompareStringsOption_ {std::nullopt};
IcuFormatter icuObjCache_[static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT)];
};
class EcmaVM {
public:
static EcmaVM *Create(const JSRuntimeOptions &options);
static void InitConfigurableParam(EcmaParamConfiguration& config);
static bool Destroy(EcmaVM *vm);
EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config);
EcmaVM();
~EcmaVM();
void SetLoop(void *loop)
{
loop_ = loop;
}
void *GetLoop() const
{
return loop_;
}
bool IsInitialized() const
{
return initialized_;
}
void SetPreForked(bool preForked)
{
preForked_ = preForked;
}
void SetPostForked(bool postForked)
{
postForked_ = postForked;
}
bool IsPreForked() const
{
return preForked_;
}
bool IsPostForked() const
{
return postForked_;
}
void SetAgentCanSuspend(bool agentCanSuspend)
{
agentCanSuspend_ = agentCanSuspend;
}
bool GetAgentCanSuspend() const
{
return agentCanSuspend_;
}
bool IsAsynTranslateClasses()
{
if (!GetJSOptions().IsAsyncLoadAbcTest()) {
return IsPostForked() && GetJSOptions().IsAsyncLoadAbc();
}
return GetJSOptions().IsAsyncLoadAbc();
}
ObjectFactory *GetFactory() const
{
return factory_;
}
void InitializePGOProfiler();
void ResetPGOProfiler();
void DisablePGOProfilerWithAOTFile(const std::string &aotFileName);
bool PUBLIC_API IsEnablePGOProfiler() const;
bool PUBLIC_API IsPgoNapi() const;
bool PUBLIC_API IsEnableMutantArray() const;
bool PUBLIC_API IsEnableElementsKind() const;
bool Initialize();
void InitializeForJit(JitThread *thread);
GCStats *GetEcmaGCStats() const
{
return gcStats_;
}
GCKeyStats *GetEcmaGCKeyStats() const
{
return gcKeyStats_;
}
void SetJSThread(JSThread *thread)
{
thread_ = thread;
}
JSThread *GetAssociatedJSThread() const
{
return thread_;
}
const JSRuntimeOptions &GetJSOptions() const
{
return options_;
}
JSRuntimeOptions &GetJSOptions()
{
return options_;
}
const EcmaParamConfiguration &GetEcmaParamConfiguration() const
{
return ecmaParamConfiguration_;
}
JSHandle<GlobalEnv> PUBLIC_API GetGlobalEnv() const
{
return thread_->GetGlobalEnv();
}
static EcmaVM *ConstCast(const EcmaVM *vm)
{
return const_cast<EcmaVM *>(vm);
}
void PUBLIC_API CheckThread() const;
JSThread *GetAndFastCheckJSThread() const;
bool CheckSingleThread() const;
ARK_INLINE uint32_t GetThreadCheckStatus() const
{
return EcmaVM::GetMultiThreadCheck() || options_.EnableThreadCheck();
}
ARK_INLINE JSThread *GetJSThread() const
{
#ifdef ECMASCRIPT_ENABLE_ASAN_THREAD_CHECK
CheckThread();
#else
if (GetThreadCheckStatus()) {
if (!GetCheckCountApi() || (CheckTimeInterval() && CheckCountNum())) {
CheckThread();
}
}
#endif
return thread_;
}
JSThread *GetJSThreadNoCheck() const
{
return thread_;
}
bool ICEnabled() const
{
return icEnabled_;
}
uint32_t IsEnableCMCGC() const
{
return isEnableCMCGC_;
}
uint64_t GetOpenHandleScopes() const
{
return openHandleScopes_;
}
void IncreaseOpenHandleScopes()
{
openHandleScopes_++;
}
void DecreaseOpenHandleScopes()
{
openHandleScopes_--;
}
void PushToNativePointerList(JSNativePointer *pointer, Concurrent isConcurrent = Concurrent::NO);
void RemoveFromNativePointerList(JSNativePointer *pointer);
void PushToDeregisterModuleList(const CString &module);
void RemoveFromDeregisterModuleList(CString module);
bool ContainInDeregisterModuleList(CString module);
JSHandle<ecmascript::JSTaggedValue> GetAndClearEcmaUncaughtException() const;
JSHandle<ecmascript::JSTaggedValue> GetEcmaUncaughtException() const;
EcmaRuntimeStat *GetRuntimeStat() const
{
return runtimeStat_;
}
void InitializeEcmaScriptRunStat();
void SetRuntimeStatEnable(bool flag);
bool IsOptionalLogEnabled() const
{
return optionalLogEnabled_;
}
JSTaggedType *GetHandleScopeStorageNext() const
{
return handleScopeStorageNext_;
}
void SetHandleScopeStorageNext(JSTaggedType *value)
{
handleScopeStorageNext_ = value;
}
JSTaggedType *GetHandleScopeStorageEnd() const
{
return handleScopeStorageEnd_;
}
void SetHandleScopeStorageEnd(JSTaggedType *value)
{
handleScopeStorageEnd_ = value;
}
int GetCurrentHandleStorageIndex() const
{
return currentHandleStorageIndex_;
}
JSTaggedType *GetPrimitiveScopeStorageNext() const
{
return primitiveScopeStorageNext_;
}
void SetPrimitiveScopeStorageNext(JSTaggedType *value)
{
primitiveScopeStorageNext_ = value;
}
JSTaggedType *GetPrimitiveScopeStorageEnd() const
{
return primitiveScopeStorageEnd_;
}
void SetPrimitiveScopeStorageEnd(JSTaggedType *value)
{
primitiveScopeStorageEnd_ = value;
}
int GetCurrentPrimitiveStorageIndex() const
{
return currentPrimitiveStorageIndex_;
}
uintptr_t *ExpandHandleStorage();
void ShrinkHandleStorage(int prevIndex);
void DeleteHandleStorage();
uintptr_t *ExpandPrimitiveStorage();
void ShrinkPrimitiveStorage(int prevIndex);
void DeletePrimitiveStorage();
size_t IterateHandle(RootVisitor &visitor);
void Iterate(RootVisitor &v);
void IterateSTWRoots(RootVisitor &v);
void IterateConcurrentRoots(RootVisitor &v);
void IterateWeakGlobalEnvList(WeakVisitor &visitor);
void IterateWeakGlobalEnvList(WeakRootVisitor &visitor);
void IterateGlobalEnvField(RootVisitor &visitor);
const Heap *GetHeap() const
{
return heap_;
}
Heap *GetHeap()
{
return heap_;
}
void CollectGarbage(TriggerGCType gcType, GCReason reason = GCReason::OTHER) const;
NativeAreaAllocator *GetNativeAreaAllocator() const
{
return nativeAreaAllocator_.get();
}
HeapRegionAllocator *GetHeapRegionAllocator() const
{
return heapRegionAllocator_.get();
}
Chunk *GetChunk() const
{
return const_cast<Chunk *>(&chunk_);
}
void ProcessNativeDelete(const WeakRootVisitor &visitor);
void ProcessReferences(const WeakRootVisitor &visitor);
void ProcessSnapShotEnv(const WeakRootVisitor& visitor);
void IteratorSnapShotEnv(WeakVisitor& visitor);
AsyncStackTrace *GetAsyncStackTrace() const
{
return asyncStackTrace_;
}
AsyncStackTraceManager *GetAsyncStackTraceManager() const
{
return asyncStackTraceManager_;
}
uint32_t GetAsyncTaskId();
bool InsertAsyncStackTrace(const JSHandle<JSPromise> &promise);
bool RemoveAsyncStackTrace(const JSHandle<JSPromise> &promise);
SnapshotEnv *GetSnapshotEnv() const
{
return snapshotEnv_;
}
tooling::JsDebuggerManager *GetJsDebuggerManager() const
{
return debuggerManager_;
}
void SetDeviceDisconnectCallback(DeviceDisconnectCallback cb)
{
deviceDisconnectCallback_ = cb;
}
DeviceDisconnectCallback GetDeviceDisconnectCallback() const
{
return deviceDisconnectCallback_;
}
void SetEnableForceGC(bool enable)
{
options_.SetEnableForceGC(enable);
}
void SetNativePtrGetter(NativePtrGetter cb)
{
nativePtrGetter_ = cb;
}
void SetNativeReferenceDataGetter(NativeReferenceDataCallbackGetter cb)
{
nativeReferenceDataGetter_ = cb;
}
NativeReferenceDataCallbackGetter GetNativeReferenceDataCallbackGetter() const
{
return nativeReferenceDataGetter_;
}
NativePtrGetter GetNativePtrGetter() const
{
return nativePtrGetter_;
}
void SetSourceMapCallback(SourceMapCallback cb)
{
sourceMapCallback_ = cb;
}
SourceMapCallback GetSourceMapCallback() const
{
return sourceMapCallback_;
}
void SetSourceMapTranslateCallback(SourceMapTranslateCallback cb)
{
sourceMapTranslateCallback_ = cb;
}
SourceMapTranslateCallback GetSourceMapTranslateCallback() const
{
return sourceMapTranslateCallback_;
}
void SetResolveBufferCallback(ResolveBufferCallback cb)
{
resolveBufferCallback_ = cb;
}
ResolveBufferCallback GetResolveBufferCallback() const
{
return resolveBufferCallback_;
}
void SetResolveBufferCallbackForHybridApp(ResolveBufferCallback cb)
{
resolveBufferCallbackForHybridApp_ = cb;
}
ResolveBufferCallback GetResolveBufferCallbackForHybridApp() const
{
return resolveBufferCallbackForHybridApp_;
}
void SetTimerTaskCallback(TimerTaskCallback callback)
{
timerTaskCallback_ = callback;
}
TimerTaskCallback GetTimerTaskCallback() const
{
return timerTaskCallback_;
}
void SetCancelTimerCallback(CancelTimerCallback callback)
{
cancelTimerCallback_ = callback;
}
CancelTimerCallback GetCancelTimerCallback() const
{
return cancelTimerCallback_;
}
void SetSearchHapPathCallBack(SearchHapPathCallBack cb)
{
SearchHapPathCallBack_ = cb;
}
SearchHapPathCallBack GetSearchHapPathCallBack() const
{
return SearchHapPathCallBack_;
}
void SetUnloadNativeModuleCallback(const UnloadNativeModuleCallback &cb)
{
unloadNativeModuleCallback_ = cb;
}
UnloadNativeModuleCallback GetUnloadNativeModuleCallback() const
{
return unloadNativeModuleCallback_;
}
void SetConcurrentCallback(ConcurrentCallback callback, void *data)
{
concurrentCallback_ = callback;
concurrentData_ = data;
}
void AddStopPreLoadCallback(const StopPreLoadSoCallback &cb)
{
stopPreLoadCallbacks_.emplace_back(cb);
}
CVector<StopPreLoadSoCallback> GetStopPreLoadCallbacks() const
{
return stopPreLoadCallbacks_;
}
void StopPreLoadSoOrAbc();
void TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint);
void WorkersetInfo(EcmaVM *workerVm);
EcmaVM *GetWorkerVm(uint32_t tid);
bool DeleteWorker(EcmaVM *workerVm);
bool SuspendWorkerVm(uint32_t tid);
void ResumeWorkerVm(uint32_t tid);
template<typename Callback>
void EnumerateWorkerVm(Callback cb)
{
LockHolder lock(mutex_);
for (const auto &item : workerList_) {
cb(item.second);
}
}
bool IsWorkerThread() const
{
return options_.IsWorker();
}
bool IsRestrictedWorkerThread() const
{
return options_.IsRestrictedWorker();
}
bool IsBundlePack() const
{
return isBundlePack_;
}
void SetIsBundlePack(bool value)
{
isBundlePack_ = value;
}
bool IsNormalizedOhmUrlPack()
{
ReadLockHolder lock(pkgContextInfoLock_);
return !pkgContextInfoList_.empty();
}
void SetPkgNameList(const CMap<CString, CString> &list)
{
WriteLockHolder lock(pkgNameListLock_);
pkgNameList_ = list;
}
void UpdatePkgNameList(const CMap<CString, CString> &list)
{
WriteLockHolder lock(pkgNameListLock_);
pkgNameList_.insert(list.begin(), list.end());
}
CMap<CString, CString> GetPkgNameList()
{
ReadLockHolder lock(pkgNameListLock_);
return pkgNameList_;
}
inline CString GetPkgName(const CString &moduleName)
{
ReadLockHolder lock(pkgNameListLock_);
auto it = pkgNameList_.find(moduleName);
if (it == pkgNameList_.end()) {
LOG_ECMA(INFO) << " Get Pkg Name failed";
return moduleName;
}
return it->second;
}
void UpdatePkgContextInfoList(const CMap<CString, CMap<CString, CVector<CString>>> &list)
{
WriteLockHolder lock(pkgContextInfoLock_);
pkgContextInfoList_.insert(list.begin(), list.end());
}
inline CMap<CString, CMap<CString, CVector<CString>>> GetPkgContextInfoList()
{
ReadLockHolder lock(pkgContextInfoLock_);
return pkgContextInfoList_;
}
inline CString GetPkgNameWithAlias(const CString &alias)
{
ReadLockHolder lock(pkgAliasListLock_);
auto it = pkgAliasList_.find(alias);
if (it == pkgAliasList_.end()) {
return alias;
}
return it->second;
}
void SetPkgAliasList(const CMap<CString, CString> &list)
{
WriteLockHolder lock(pkgAliasListLock_);
pkgAliasList_ = list;
}
void UpdatePkgAliasList(const CMap<CString, CString> &list)
{
WriteLockHolder lock(pkgAliasListLock_);
pkgAliasList_.insert(list.begin(), list.end());
}
CMap<CString, CString> GetPkgAliasList()
{
ReadLockHolder lock(pkgAliasListLock_);
return pkgAliasList_;
}
void SetMockModuleList(const std::map<std::string, std::string> &list)
{
for (auto it = list.begin(); it != list.end(); ++it) {
mockModuleList_.emplace(it->first.c_str(), it->second.c_str());
}
}
inline bool IsMockModule(const CString &moduleStr) const
{
if (mockModuleList_.empty()) {
return false;
}
auto it = mockModuleList_.find(moduleStr);
if (it == mockModuleList_.end()) {
return false;
}
return true;
}
inline CString GetMockModule(const CString &module) const
{
auto it = mockModuleList_.find(module);
if (it == mockModuleList_.end()) {
LOG_ECMA(FATAL) << " Get Mock Module failed";
}
return it->second;
}
#if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
void DeleteHeapProfile();
HeapProfilerInterface *GetHeapProfile();
void SetHeapProfile(HeapProfilerInterface *heapProfile) { heapProfile_ = heapProfile; }
HeapProfilerInterface *GetOrNewHeapProfile();
#if defined(PANDA_JS_ETS_HYBRID_MODE)
void DeleteHybridHeapProfile();
HybridHeapProfiler *GetOrNewHybridHeapProfiler();
#endif
void StartHeapTracking();
void StopHeapTracking();
#endif
void SetAssetPath(const CString &assetPath)
{
assetPath_ = assetPath;
}
CString GetAssetPath() const
{
return assetPath_;
}
inline void SetBundleName(const CString &bundleName)
{
bundleName_ = bundleName;
}
CString GetBundleName() const
{
return bundleName_;
}
void SetModuleName(const CString &moduleName)
{
moduleName_ = moduleName;
}
CString GetModuleName() const
{
return moduleName_;
}
std::pair<std::string, std::string> GetCurrentModuleInfo(bool needRecordName = false);
void SetHmsModuleList(const std::vector<panda::HmsMap> &list);
bool IsHmsModule(const CString &moduleStr) const;
CString GetHmsModule(const CString &module) const;
const std::map<CString, HmsMap>& GetHmsModuleList() const
{
return hmsModuleList_;
}
void SetpkgContextInfoList(const CMap<CString, CMap<CString, CVector<CString>>> &list);
#if ENABLE_LATEST_OPTIMIZATION
void GetPkgContextInfoListElements(const CString &moduleName, const CString &packageName,
CVector<CString> &resultList);
#endif
void SetOhExportsList(const CUnorderedMap<CString, CUnorderedMap<CString, CUnorderedSet<CString>>> &ohExportsMap);
void UpdateOhExportsList(const CUnorderedMap<CString, CUnorderedMap<CString,
CUnorderedSet<CString>>> &ohExportsMap);
bool CheckOhExportsWithOhmurl(const CString &moduleName, const CString &packageName, const CString &ohmurl);
CUnorderedMap<CString, CUnorderedMap<CString, CUnorderedSet<CString>>> GetOhExportList()
{
ReadLockHolder lock(ohExportListLock_);
return ohExportsList_;
}
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
CpuProfiler *GetProfiler() const
{
return profiler_;
}
void SetProfiler(CpuProfiler *profiler)
{
profiler_ = profiler;
}
#endif
#if defined(ECMASCRIPT_SUPPORT_TRACING)
Tracing *GetTracing() const
{
return tracing_;
}
void SetTracing(Tracing *tracing)
{
tracing_ = tracing;
}
#endif
std::shared_ptr<PGOProfiler> GetPGOProfiler() const
{
return pgoProfiler_;
}
void PreFork();
void PostFork(const JSRuntimeOptions &option);
JSTaggedValue GetMethodByIndex(MethodIndex idx);
QuickFixManager *GetQuickFixManager() const
{
return quickFixManager_;
}
JSTaggedValue FastCallAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp);
void RegisterUncatchableErrorHandler(const UncatchableErrorHandler &uncatchableErrorHandler)
{
uncatchableErrorHandler_ = uncatchableErrorHandler;
}
UncatchableErrorHandler GetUncatchableErrorHandler() const
{
return uncatchableErrorHandler_;
}
void HandleUncatchableError();
void DumpCallTimeInfo();
FunctionCallTimer *GetCallTimer() const
{
return callTimer_;
}
EcmaStringTable *GetEcmaStringTable() const
{
ASSERT(stringTable_ != nullptr);
return stringTable_;
}
void IncreaseCallDepth()
{
callDepth_++;
}
void DecreaseCallDepth()
{
ASSERT(callDepth_ > 0);
callDepth_--;
}
bool IsTopLevelCallDepth()
{
return callDepth_ == 0;
}
void SetProfilerState(bool state)
{
isProfiling_ = state;
}
bool GetProfilerState()
{
return isProfiling_;
}
JSObjectResizingStrategy *GetJSObjectResizingStrategy()
{
return strategy_;
}
CMap<uint32_t, EcmaVM *> GetWorkList() const
{
return workerList_;
}
int GetProcessStartRealtime() const
{
return processStartRealtime_;
}
void SetProcessStartRealtime(int value)
{
processStartRealtime_ = value;
}
Jit *GetJit() const;
bool PUBLIC_API IsEnableFastJit() const;
bool PUBLIC_API IsEnableBaselineJit() const;
bool IsEnableOsr() const
{
return isEnableOsr_;
}
void SetEnableOsr(bool state)
{
isEnableOsr_ = state;
}
PUBLIC_API AOTFileManager *GetAOTFileManager() const
{
return aotFileManager_;
}
uint32_t GetTid() const;
std::vector<NativePointerCallbackData> &GetConcurrentNativePointerCallbacks()
{
return concurrentNativeCallbacks_;
}
AsyncNativeCallbacksPack &GetAsyncNativePointerCallbacksPack()
{
return asyncNativeCallbacksPack_;
}
void SetIsJitCompileVM(bool isJitCompileVM)
{
isJitCompileVM_ = isJitCompileVM;
}
bool IsJitCompileVM() const
{
return isJitCompileVM_;
}
static void SetMultiThreadCheck(bool multiThreadCheck)
{
multiThreadCheck_ = multiThreadCheck;
}
PUBLIC_API static bool GetMultiThreadCheck()
{
return multiThreadCheck_;
}
static void SetCheckCountApi(bool checkCountApi)
{
checkCountApi_ = checkCountApi;
}
PUBLIC_API static bool GetCheckCountApi()
{
return checkCountApi_;
}
static void SetDetectionConfig(const DFXJSNApi::MultithreadingDetectionOptions& config)
{
detectionConfig_.abort.store(config.abort.load());
constexpr int64_t MIN_CHECK_COUNT_NUM = 100;
if (config.frequency.load() < MIN_CHECK_COUNT_NUM) {
LOG_ECMA(ERROR) << "checkCountNum must be >= 100, but got " << config.frequency.load();
} else {
detectionConfig_.frequency.store(config.frequency.load());
}
constexpr int64_t MAX_CHECKINTERVAL = 1440;
if (config.interval.load() < 0 || config.interval.load() > MAX_CHECKINTERVAL) {
LOG_ECMA(ERROR) << "checkInterval must within [0, 1440] minutes, but got " << config.interval.load();
} else {
detectionConfig_.interval.store(config.interval.load());
}
}
PUBLIC_API static const DFXJSNApi::MultithreadingDetectionOptions &GetDetectionConfig()
{
return detectionConfig_;
}
bool CheckCountNum() const
{
if (count_ % detectionConfig_.frequency.load() == 0) {
count_ = 1;
return true;
} else {
count_++;
}
return false;
}
bool CheckTimeInterval() const
{
uint64_t currentTime = GetTimeStamp();
uint64_t lastTime = lastCheckTime_.load();
if (lastTime == 0) {
return true;
}
if (currentTime - lastTime >= detectionConfig_.interval.load() * SECOND_PER_MINUTE * MS_PER_SECOND) {
return true;
}
return false;
}
uint64_t GetTimeStamp() const
{
struct timespec ts{};
clock_gettime(CLOCK_REALTIME, &ts);
return ((uint64_t)ts.tv_sec * MS_PER_SECOND) + (((uint64_t)ts.tv_nsec) / NS_PER_SECOND);
}
static void SetErrorInfoEnhance(bool errorInfoEnhance)
{
errorInfoEnhanced_ = errorInfoEnhance;
}
static bool GetErrorInfoEnhance()
{
return errorInfoEnhanced_;
}
bool SetHeapMemoryPressure(const DFXJSNApi::HeapMemoryPressureOptions &options, Local<FunctionRef> callback);
void ResetMemoryPressure();
double GetLocalMemoryPressureThreshold() const
{
return localMemoryPressureThreshold_;
}
double GetSharedMemoryPressureThreshold() const
{
return sharedMemoryPressureThreshold_;
}
double GetProcessMemoryPressureThreshold() const
{
return processMemoryPressureThreshold_;
}
bool SetMemoryPressureCallback(Local<FunctionRef> callback)
{
if (!memoryPressureCallback_.IsEmpty()) {
LOG_ECMA(WARN) << "SetMemoryPressureCallback: callback already set, cannot set again";
return false;
}
memoryPressureCallback_ = Global<FunctionRef>(this, callback);
return true;
}
Local<FunctionRef> GetMemoryPressureCallback() const
{
if (memoryPressureCallback_.IsEmpty()) {
return Local<FunctionRef>();
}
return memoryPressureCallback_.ToLocal(this);
}
bool HasMemoryPressureCallback()
{
return !memoryPressureCallback_.IsEmpty();
}
void TriggerMemoryPressureCallback(const char *heapType);
bool GetIsInMemoryPressureCallback() const
{
return isInMemoryPressureCallback_;
}
void SetInMemoryPressureCallback(bool inCallback)
{
isInMemoryPressureCallback_ = inCallback;
}
void CheckHeapMemoryPressure(const Heap *heap);
void CheckSharedHeapMemoryPressure();
void CheckAndTriggerMemoryPressureCallback();
bool GetNeedProcessMemoryPressureCallback() const
{
return needProcessMemoryPressureCallback_;
}
bool GetNeedSharedMemoryPressureCallback() const
{
return needSharedMemoryPressureCallback_;
}
void SetNeedProcessMemoryPressureCallback(bool flag)
{
needProcessMemoryPressureCallback_ = flag;
}
void SetNeedSharedMemoryPressureCallback(bool flag)
{
needSharedMemoryPressureCallback_ = flag;
}
static void InitializeIcuData(const JSRuntimeOptions &options);
static int InitializeStartRealTime();
ArkTSMode GetArkTSMode() const
{
return options_.GetArkTSMode();
}
#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
void ResetScopeLockStats()
{
enterThreadManagedScopeCount_ = 0;
enterJsiNativeScopeCount_ = 0;
enterFastNativeScopeCount_ = 0;
updateThreadStateTransCount_ = 0;
stringTableLockCount_ = 0;
}
bool IsCollectingScopeLockStats() const
{
return isCollectingScopeLockStats_;
}
void StartCollectingScopeLockStats()
{
isCollectingScopeLockStats_ = true;
}
void StopCollectingScopeLockStats()
{
isCollectingScopeLockStats_ = false;
}
int GetEnterThreadManagedScopeCount() const
{
return enterThreadManagedScopeCount_;
}
void IncreaseEnterThreadManagedScopeCount()
{
enterThreadManagedScopeCount_++;
}
int GetEnterFastNativeScopeCount() const
{
return enterFastNativeScopeCount_;
}
void IncreaseEnterFastNativeScopeCount()
{
enterFastNativeScopeCount_++;
}
int GetEnterJsiNativeScopeCount() const
{
return enterJsiNativeScopeCount_;
}
void IncreaseEnterJsiNativeScopeCount()
{
enterJsiNativeScopeCount_++;
}
int GetUpdateThreadStateTransCount() const
{
return updateThreadStateTransCount_;
}
void IncreaseUpdateThreadStateTransCount()
{
updateThreadStateTransCount_++;
}
int GetStringTableLockCount() const
{
return stringTableLockCount_;
}
void IncreaseStringTableLockCount()
{
stringTableLockCount_++;
}
#endif
bool GetEnableJitLogSkip() const
{
return enableJitLogSkip_;
}
void SetEnableJitLogSkip(bool flag)
{
enableJitLogSkip_ = flag;
}
void AddAOTSnapShotStats(std::string tag, uint32_t count = 1)
{
aotSnapShotStatsMap_[tag] += count;
}
IntlCache& GetIntlCache()
{
return intlCache_;
}
void PUBLIC_API PrintAOTSnapShotStats();
void SetVMAPIVersion(uint32_t APIVersion)
{
apiVersion_ = APIVersion;
}
uint32_t GetVMAPIVersion()
{
return apiVersion_;
}
JSTaggedValue GetRegisterSymbols() const
{
return registerSymbols_;
}
void SetRegisterSymbols(JSTaggedValue value)
{
registerSymbols_ = value;
}
JSTaggedValue GetFinRegLists() const
{
return finRegLists_;
}
void SetFinRegLists(JSTaggedValue value)
{
finRegLists_ = value;
}
JSHandle<job::MicroJobQueue> GetMicroJobQueue() const;
bool HasPendingJob() const;
bool ExecutePromisePendingJob();
void SetPromiseRejectCallback(PromiseRejectCallback cb)
{
promiseRejectCallback_ = cb;
}
PromiseRejectCallback GetPromiseRejectCallback() const
{
return promiseRejectCallback_;
}
void SetHostPromiseRejectionTracker(HostPromiseRejectionTracker cb)
{
hostPromiseRejectionTracker_ = cb;
}
void PromiseRejectionTracker(const JSHandle<JSPromise> &promise,
const JSHandle<JSTaggedValue> &reason, PromiseRejectionEvent operation)
{
if (hostPromiseRejectionTracker_ != nullptr) {
hostPromiseRejectionTracker_(this, promise, reason, operation, data_);
}
}
void SetPromiseRejectInfoData(void* data)
{
data_ = data;
}
bool IsExecutingPendingJob() const
{
return isProcessingPendingJob_.load();
}
JSTaggedValue PUBLIC_API FindUnsharedConstpool(JSTaggedValue sharedConstpool);
JSTaggedValue FindUnsharedConstpool(int32_t constpoolIndex);
JSTaggedValue PUBLIC_API FindOrCreateUnsharedConstpool(JSTaggedValue sharedConstpool);
JSTaggedValue PUBLIC_API CreateUnsharedConstpool(JSTaggedValue sharedConstpool);
void EraseUnusedConstpool(const JSPandaFile *jsPandaFile, int32_t index, int32_t constpoolIndex);
JSTaggedValue PUBLIC_API FindConstpool(const JSPandaFile *jsPandaFile, int32_t index);
JSTaggedValue PUBLIC_API FindConstpool(const JSPandaFile *jsPandaFile, panda_file::File::EntityId id);
bool HasCachedConstpool(const JSPandaFile *jsPandaFile) const;
JSHandle<ConstantPool> AddOrUpdateConstpool(const JSPandaFile *jsPandaFile,
JSHandle<ConstantPool> constpool,
int32_t index = 0);
void SetUnsharedConstpool(JSHandle<ConstantPool> sharedConstpool, JSTaggedValue unsharedConstpool);
void SetUnsharedConstpool(int32_t constpoolIndex, JSTaggedValue unsharedConstpool);
void CreateAllConstpool(const JSPandaFile *jsPandaFile);
std::optional<std::reference_wrapper<CMap<int32_t, JSTaggedValue>>> FindConstpools(const JSPandaFile *jsPandaFile);
void UpdateConstpoolWhenDeserialAI(const std::string& fileName,
JSHandle<ConstantPool> aiCP,
int32_t index = 0);
JSHandle<ConstantPool> PUBLIC_API FindOrCreateConstPool(const JSPandaFile *jsPandaFile,
panda_file::File::EntityId id);
void ForEachSharedConstpool(const JSPandaFile *jsPandaFile, const ForEachCallback<JSTaggedValue>& cb);
void ClearCachedConstantPool()
{
cachedSharedConstpools_.clear();
}
JSTaggedValue *GetUnsharedConstpoolsPointer() const
{
return unsharedConstpools_;
}
#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES
void SetBytecodeStatsStack(std::unordered_map<BytecodeInstruction::Opcode, int> &bytecodeStatsMap)
{
bytecodeStatsStack_.push(bytecodeStatsMap);
}
std::stack<std::unordered_map<BytecodeInstruction::Opcode, int>>& GetBytecodeStatsStack()
{
return bytecodeStatsStack_;
}
void PrintCollectedByteCode();
#endif
RegExpParserCache *GetRegExpParserCache() const
{
ASSERT(regExpParserCache_ != nullptr);
return regExpParserCache_;
}
WaiterListNode *GetWaiterListNode()
{
return &waiterListNode_;
}
AbcBufferCache *GetAbcBufferCache() const
{
return abcBufferCache_;
}
void **GetPcVectorData()
{
return pcVector_.data();
}
const void* const *GetPcVectorData() const
{
return pcVector_.data();
}
int GetPcVectorSize() const
{
return realSize_;
}
void SetPcVectorSize(int size)
{
realSize_ = size;
}
void AddSustainingJSHandle(SustainingJSHandle *sustainingHandle);
void RemoveSustainingJSHandle(SustainingJSHandle *sustainingHandle);
kungfu::PGOTypeManager* GetPTManager() const
{
return ptManager_;
}
OptCodeProfiler* GetOptCodeProfiler() const
{
return optCodeProfiler_;
}
TypedOpProfiler* GetTypedOpProfiler() const
{
return typedOpProfiler_;
}
FunctionProtoTransitionTable* GetFunctionProtoTransitionTable() const
{
return functionProtoTransitionTable_;
}
void PrintOptStat();
void DumpAOTInfo() const DUMP_API_ATTR;
std::tuple<uint64_t, uint8_t*, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr,
bool isDeopt) const;
void LoadStubFile();
bool LoadAOTFilesInternal(const std::string& aotFileName);
bool LoadAOTFiles(const std::string& aotFileName);
void PUBLIC_API LoadProtoTransitionTable(JSTaggedValue constpool);
void PUBLIC_API ResetProtoTransitionTableOnConstpool(JSTaggedValue constpool);
void AddPatchModule(const CString &recordName, const JSHandle<JSTaggedValue> moduleRecord)
{
cachedPatchModules_.emplace(recordName, moduleRecord);
}
JSHandle<JSTaggedValue> FindPatchModule(const CString &recordName) const
{
auto iter = cachedPatchModules_.find(recordName);
if (iter != cachedPatchModules_.end()) {
return iter->second;
}
return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Hole());
}
void ClearPatchModules()
{
GlobalHandleCollection globalHandleCollection(thread_);
for (auto &item : cachedPatchModules_) {
globalHandleCollection.Dispose(item.second);
}
cachedPatchModules_.clear();
}
StageOfColdReload GetStageOfColdReload() const
{
return stageOfColdReload_;
}
void SetStageOfColdReload(StageOfColdReload stageOfColdReload)
{
stageOfColdReload_ = stageOfColdReload;
}
void SetApplicationVersionCode(const uint32_t versionCode)
{
applicationVersionCode_ = versionCode;
}
uint32_t GetApplicationVersionCode() const
{
return applicationVersionCode_;
}
void RecordGlobalEnv(GlobalEnv *globalEnv)
{
globalEnvRecordList_.push_back(static_cast<JSTaggedType>(ToUintPtr(globalEnv)));
}
void AddHandleScopeDepth()
{
++handleScopeDepth_;
}
void DelHandleScopeDepth()
{
--handleScopeDepth_;
}
uint32_t GetHandleScopeDepth() const
{
return handleScopeDepth_;
}
void SetEnableRuntimeAsyncStack(bool state);
bool IsEnableRuntimeAsyncStack() const
{
return enableRuntimeAsyncStack_;
}
void InsertWrappedNativePointerAddrsMap(const JSTaggedType addr, void* nativeAddress)
{
wrappedNativePointerAddrsMap_.emplace(addr, nativeAddress);
}
const CUnorderedMap<JSTaggedType, void*>& GetWrappedNativePointerAddrsMap() const
{
return wrappedNativePointerAddrsMap_;
}
void ClearWrappedNativePointerAddrsMap()
{
wrappedNativePointerAddrsMap_.clear();
}
JSTaggedValue ExecuteAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp,
bool needPushArgv);
#if ECMASCRIPT_ENABLE_ARK_STEED
JSTaggedValue ExecuteArkSteed(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp);
#endif
static void ClearKeptObjects(JSThread *thread);
static void AddToKeptObjects(JSThread *thread, JSHandle<JSTaggedValue> value);
void AddModuleManager(ModuleManager *moduleManager);
JSTaggedValue GetTypedArrayName(uint8_t type) const
{
ASSERT(type >= 0);
ASSERT(type < typedArrayNameTable_.size());
return typedArrayNameTable_[type];
}
JSTaggedValue GetSharedTypedArrayName(uint8_t type) const
{
ASSERT(type >= 0);
ASSERT(type < sharedTypedArrayNameTable_.size());
return sharedTypedArrayNameTable_[type];
}
std::string GetExtraJSCrashMessage() const;
size_t RegisterExtraJSCrashMessageCallback(const std::string_view &name, ExtraJSCrashMessageCallback cb);
static void NotifyANR();
#ifdef PANDA_JS_ETS_HYBRID_MODE
ECMAVM_PUBLIC_HYBRID_MODE_EXTENSION()
#endif
ECMAVM_PUBLIC_HYBRID_EXTENSION();
protected:
ECMAVM_PROTECTED_HYBRID_EXTENSION();
double localMemoryPressureThreshold_ = 0.0;
double sharedMemoryPressureThreshold_ = 0.0;
double processMemoryPressureThreshold_ = 0.0;
class MemoryPressureCallbackScope {
public:
explicit MemoryPressureCallbackScope(EcmaVM* vm) : vm_(vm)
{
vm_->SetInMemoryPressureCallback(true);
}
~MemoryPressureCallbackScope()
{
vm_->SetInMemoryPressureCallback(false);
}
private:
EcmaVM* vm_;
};
Global<FunctionRef> memoryPressureCallback_;
bool isInMemoryPressureCallback_ = false;
bool needProcessMemoryPressureCallback_ = false;
bool needSharedMemoryPressureCallback_ = false;
private:
void ClearBufferData();
void ClearConstpoolBufferData();
void CheckStartCpuProfiler();
void SetMicroJobQueue(job::MicroJobQueue *queue);
void GenerateInternalNativeMethods();
void CacheToGlobalConstants(JSTaggedValue value, ConstantIndex constant);
JSTaggedValue FindConstpoolFromContextCache(const JSPandaFile *jsPandaFile, int32_t index);
void AddContextConstpoolCache(const JSPandaFile *jsPandaFile,
JSHandle<ConstantPool> constpool,
int32_t index);
JSTaggedValue FindCachedConstpoolAndLoadAiIfNeeded(const JSPandaFile *jsPandaFile, int32_t index);
void GrowUnsharedConstpoolArray(int32_t index);
void ResizeUnsharedConstpoolArray(int32_t oldCapacity, int32_t minCapacity);
void ClearUnsharedConstpoolArray()
{
if (unsharedConstpools_ != nullptr) {
delete[] unsharedConstpools_;
unsharedConstpools_ = nullptr;
thread_->SetUnsharedConstpools(reinterpret_cast<uintptr_t>(nullptr));
thread_->SetUnsharedConstpoolsArrayLen(0);
}
}
int32_t GetUnsharedConstpoolsArrayLen() const
{
return unsharedConstpoolsArrayLen_;
}
void SetUnsharedConstpoolsArrayLen(int32_t len)
{
unsharedConstpoolsArrayLen_ = len;
}
void CJSExecution(JSHandle<JSFunction> &func, JSHandle<JSTaggedValue> &thisArg,
const JSPandaFile *jsPandaFile, std::string_view entryPoint);
JSTaggedValue InvokeEcmaAotEntrypoint(JSHandle<JSFunction> mainFunc, JSHandle<JSTaggedValue> &thisArg,
const JSPandaFile *jsPandaFile, std::string_view entryPoint,
CJSInfo *cjsInfo = nullptr);
Expected<JSTaggedValue, bool> InvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile, const CString& entryPoint,
const ExecuteTypes &executeType = ExecuteTypes::STATIC);
Expected<JSTaggedValue, bool> InvokeEcmaEntrypointForHotReload(
const JSPandaFile *jsPandaFile, const CString& entryPoint, const ExecuteTypes &executeType);
Expected<JSTaggedValue, bool> CommonInvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile,
const CString& entryPoint, JSHandle<JSFunction> &func, const ExecuteTypes &executeType);
void InitTypedArrayNameTable(const GlobalEnvConstants *globalConst);
NO_MOVE_SEMANTIC(EcmaVM);
NO_COPY_SEMANTIC(EcmaVM);
uint64_t openHandleScopes_ {0};
CUnorderedMap<JSTaggedType, void*> wrappedNativePointerAddrsMap_ {};
JSRuntimeOptions options_;
bool icEnabled_ {true};
uint32_t isEnableCMCGC_ {0};
bool initialized_ {false};
bool preForked_ {false};
bool postForked_ {false};
bool agentCanSuspend_ {true};
GCStats *gcStats_ {nullptr};
GCKeyStats *gcKeyStats_ {nullptr};
EcmaStringTable *stringTable_ {nullptr};
PUBLIC_API static std::atomic<bool> multiThreadCheck_;
PUBLIC_API static std::atomic<bool> checkCountApi_;
PUBLIC_API static DFXJSNApi::MultithreadingDetectionOptions detectionConfig_;
PUBLIC_API static std::atomic<uint64_t> lastCheckTime_;
PUBLIC_API static std::atomic<uint64_t> count_;
static bool errorInfoEnhanced_;
CMap<const JSPandaFile *, CMap<int32_t, JSTaggedValue>> cachedSharedConstpools_ {};
JSTaggedValue* unsharedConstpools_ = nullptr;
int32_t unsharedConstpoolsArrayLen_ = UNSHARED_CONSTANTPOOL_COUNT;
static constexpr int32_t SHARED_CONSTPOOL_KEY_NOT_FOUND = INT32_MAX;
static constexpr uint64_t SECOND_PER_MINUTE = 60;
static constexpr uint64_t MS_PER_SECOND = 1000;
static constexpr uint64_t NS_PER_SECOND = 1000000;
uint32_t apiVersion_ = 8;
std::unique_ptr<NativeAreaAllocator> nativeAreaAllocator_;
std::unique_ptr<HeapRegionAllocator> heapRegionAllocator_;
Chunk chunk_;
Heap *heap_ {nullptr};
ObjectFactory *factory_ {nullptr};
std::vector<NativePointerCallbackData> concurrentNativeCallbacks_ {};
AsyncNativeCallbacksPack asyncNativeCallbacksPack_ {};
JSThread *thread_ {nullptr};
EcmaRuntimeStat *runtimeStat_ {nullptr};
CUnorderedMap<std::string, uint32_t> aotSnapShotStatsMap_;
SnapshotEnv *snapshotEnv_ {nullptr};
bool optionalLogEnabled_ {false};
tooling::JsDebuggerManager *debuggerManager_ {nullptr};
AsyncStackTrace *asyncStackTrace_ {nullptr};
bool enableRuntimeAsyncStack_ = false;
AsyncStackTraceManager *asyncStackTraceManager_ {nullptr};
bool isBundlePack_ {true};
#if !WIN_OR_MAC_OR_IOS_PLATFORM
HeapProfilerInterface *heapProfile_ {nullptr};
HybridHeapProfiler *hybridHeapProfiler_ {nullptr};
#endif
CString assetPath_;
CString bundleName_;
CString moduleName_;
std::set<CString> deregisterModuleList_;
CMap<CString, CString> mockModuleList_;
std::map<CString, HmsMap> hmsModuleList_;
CMap<CString, CString> pkgNameList_;
CMap<CString, CMap<CString, CVector<CString>>> pkgContextInfoList_;
CMap<CString, CString> pkgAliasList_;
CUnorderedMap<CString, CUnorderedMap<CString, CUnorderedSet<CString>>> ohExportsList_;
RWLock pkgContextInfoLock_;
RWLock pkgAliasListLock_;
RWLock pkgNameListLock_;
RWLock ohExportListLock_;
CVector<StopPreLoadSoCallback> stopPreLoadCallbacks_;
NativePtrGetter nativePtrGetter_ {nullptr};
SourceMapCallback sourceMapCallback_ {nullptr};
SourceMapTranslateCallback sourceMapTranslateCallback_ {nullptr};
NativeReferenceDataCallbackGetter nativeReferenceDataGetter_ {nullptr};
void *loop_ {nullptr};
ResolveBufferCallback resolveBufferCallback_ {nullptr};
ResolveBufferCallback resolveBufferCallbackForHybridApp_ {nullptr};
TimerTaskCallback timerTaskCallback_ {nullptr};
CancelTimerCallback cancelTimerCallback_ {nullptr};
UnloadNativeModuleCallback unloadNativeModuleCallback_ {nullptr};
ConcurrentCallback concurrentCallback_ {nullptr};
void *concurrentData_ {nullptr};
SearchHapPathCallBack SearchHapPathCallBack_ {nullptr};
EcmaParamConfiguration ecmaParamConfiguration_;
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
CpuProfiler *profiler_ {nullptr};
#endif
#if defined(ECMASCRIPT_SUPPORT_TRACING)
Tracing *tracing_ {nullptr};
#endif
FunctionCallTimer *callTimer_ {nullptr};
JSObjectResizingStrategy *strategy_ {nullptr};
static void *InternalMethodTable[static_cast<uint8_t>(MethodIndex::METHOD_END)];
CVector<JSTaggedValue> internalNativeMethods_;
uint32_t handleScopeDepth_ {0};
QuickFixManager *quickFixManager_ {nullptr};
std::shared_ptr<PGOProfiler> pgoProfiler_ {nullptr};
AOTFileManager *aotFileManager_ {nullptr};
kungfu::PGOTypeManager* ptManager_ {nullptr};
size_t callDepth_ {0};
bool isProfiling_ {false};
DeviceDisconnectCallback deviceDisconnectCallback_ {nullptr};
UncatchableErrorHandler uncatchableErrorHandler_ {nullptr};
IntlCache intlCache_;
friend class Snapshot;
friend class SnapshotProcessor;
friend class ObjectFactory;
friend class ValueSerializer;
friend class panda::JSNApi;
friend class JSPandaFileExecutor;
friend class JitVM;
CMap<uint32_t, EcmaVM *> workerList_ {};
Mutex mutex_;
bool isEnableOsr_ {false};
bool isJitCompileVM_ {false};
SustainingJSHandleList *sustainingJSHandleList_ {nullptr};
int processStartRealtime_ = 0;
bool enableJitLogSkip_ = true;
PromiseRejectCallback promiseRejectCallback_ {nullptr};
HostPromiseRejectionTracker hostPromiseRejectionTracker_ {nullptr};
void* data_{nullptr};
std::vector<void*> pcVector_ {};
int realSize_ = 0;
JSTaggedValue finRegLists_ {JSTaggedValue::Hole()};
JSTaggedValue registerSymbols_ {JSTaggedValue::Hole()};
JSTaggedValue microJobQueue_ {JSTaggedValue::Hole()};
std::atomic<bool> isProcessingPendingJob_{false};
std::vector<JSTaggedValue> typedArrayNameTable_;
std::vector<JSTaggedValue> sharedTypedArrayNameTable_;
#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT
bool isCollectingScopeLockStats_ = false;
int enterThreadManagedScopeCount_ = 0;
int enterFastNativeScopeCount_ = 0;
int enterJsiNativeScopeCount_ = 0;
int updateThreadStateTransCount_ = 0;
int stringTableLockCount_ = 0;
#endif
#if ECMASCRIPT_ENABLE_COLLECTING_OPCODES
std::stack<std::unordered_map<BytecodeInstruction::Opcode, int>> bytecodeStatsStack_;
#endif
static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10;
static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2;
static constexpr int32_t MIN_HANDLE_STORAGE_SIZE = 2;
JSTaggedType *handleScopeStorageNext_ {nullptr};
JSTaggedType *handleScopeStorageEnd_ {nullptr};
std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> handleStorageNodes_ {};
int32_t currentHandleStorageIndex_ {-1};
static constexpr int32_t MIN_PRIMITIVE_STORAGE_SIZE = 2;
JSTaggedType *primitiveScopeStorageNext_ {nullptr};
JSTaggedType *primitiveScopeStorageEnd_ {nullptr};
std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> primitiveStorageNodes_ {};
int32_t currentPrimitiveStorageIndex_ {-1};
FunctionProtoTransitionTable* functionProtoTransitionTable_ {nullptr};
OptCodeProfiler* optCodeProfiler_ {nullptr};
TypedOpProfiler* typedOpProfiler_ {nullptr};
RegExpParserCache *regExpParserCache_ {nullptr};
WaiterListNode waiterListNode_;
AbcBufferCache *abcBufferCache_ {nullptr};
CMap<CString, JSHandle<JSTaggedValue>> cachedPatchModules_;
StageOfColdReload stageOfColdReload_ = StageOfColdReload::NOT_COLD_RELOAD;
std::vector<JSTaggedType> globalEnvRecordList_;
using ExtraJSCrashMessageCallbackTuple = std::pair<std::string, ExtraJSCrashMessageCallback>;
std::vector<ExtraJSCrashMessageCallbackTuple> extraJSCrashMessageCallbacks_{};
class ModuleManagers {
Mutex CMCGCMutex_;
std::vector<ModuleManager *> moduleManagersVec_ {};
public:
void Iterate(RootVisitor &v);
template <typename T>
void PushBack(T moduleManager);
void DestroyAllNativeObj();
void Clear();
} moduleManagers_;
uint32_t applicationVersionCode_ {0};
#ifdef PANDA_JS_ETS_HYBRID_MODE
ECMAVM_PRIVATE_HYBRID_EXTENSION();
#endif
};
class HandleScopeDepthScope {
public:
explicit HandleScopeDepthScope(EcmaVM* vm): vm_(vm), initDepth_(vm->GetHandleScopeDepth()) {}
~HandleScopeDepthScope()
{
uint32_t curDepth = vm_->GetHandleScopeDepth();
if (curDepth < initDepth_) {
LOG_ECMA(ERROR) << "Handle scope not match! init depth: " << initDepth_ << " current depth: " << curDepth;
}
}
private:
EcmaVM* vm_ {nullptr};
uint32_t initDepth_ {0U};
};
}
}
#endif