mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
69094056b8
Signed-off-by: Gymee <yumeijie@huawei.com> Change-Id: I794a5ee770f251e6fea4de5058575519ff0490e6
507 lines
13 KiB
C++
507 lines
13 KiB
C++
/*
|
|
* Copyright (c) 2021-2022 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 <tuple>
|
|
|
|
#include "ecmascript/base/config.h"
|
|
#include "ecmascript/ecma_string_table.h"
|
|
#include "ecmascript/js_handle.h"
|
|
#include "ecmascript/js_method.h"
|
|
#include "ecmascript/js_runtime_options.h"
|
|
#include "ecmascript/mem/c_containers.h"
|
|
#include "ecmascript/mem/c_string.h"
|
|
#include "ecmascript/mem/chunk_containers.h"
|
|
#include "ecmascript/mem/gc_stats.h"
|
|
#include "ecmascript/mem/heap.h"
|
|
#include "ecmascript/mem/object_xray.h"
|
|
#include "ecmascript/mem/space.h"
|
|
#include "ecmascript/taskpool/task.h"
|
|
#include "ecmascript/tooling/interface/js_debugger_manager.h"
|
|
#include "ecmascript/snapshot/mem/snapshot_serialize.h"
|
|
#include "include/panda_vm.h"
|
|
#include "libpandabase/macros.h"
|
|
|
|
namespace panda {
|
|
namespace panda_file {
|
|
class File;
|
|
} // namespace panda_file
|
|
|
|
namespace ecmascript {
|
|
class GlobalEnv;
|
|
class ObjectFactory;
|
|
class RegExpParserCache;
|
|
class EcmaRuntimeStat;
|
|
class Heap;
|
|
class HeapTracker;
|
|
class JSNativePointer;
|
|
class Program;
|
|
class CpuProfiler;
|
|
class RegExpExecResultCache;
|
|
class JSPromise;
|
|
enum class PromiseRejectionEvent : uint8_t;
|
|
class JSPandaFileManager;
|
|
class JSPandaFile;
|
|
namespace job {
|
|
class MicroJobQueue;
|
|
} // namespace job
|
|
|
|
namespace tooling {
|
|
class NotificationManager;
|
|
class JsDebuggerManager;
|
|
} // namespace tooling
|
|
|
|
template<typename T>
|
|
class JSHandle;
|
|
class JSArrayBuffer;
|
|
class JSFunction;
|
|
class Program;
|
|
class TSLoader;
|
|
class ModuleManager;
|
|
class AotCodeInfo;
|
|
|
|
using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
|
|
const JSHandle<JSPromise> promise,
|
|
const JSHandle<JSTaggedValue> reason,
|
|
PromiseRejectionEvent operation,
|
|
void* data);
|
|
using PromiseRejectCallback = void (*)(void* info);
|
|
|
|
class EcmaVM : public PandaVM {
|
|
public:
|
|
static EcmaVM *Cast(PandaVM *object)
|
|
{
|
|
return reinterpret_cast<EcmaVM *>(object);
|
|
}
|
|
|
|
static EcmaVM *Create(const JSRuntimeOptions &options);
|
|
|
|
static EcmaVM *Create(Runtime *runtime);
|
|
|
|
static bool Destroy(PandaVM *vm);
|
|
|
|
explicit EcmaVM(JSRuntimeOptions options);
|
|
|
|
EcmaVM();
|
|
|
|
~EcmaVM() override;
|
|
|
|
bool IsInitialized() const
|
|
{
|
|
return vmInitialized_;
|
|
}
|
|
|
|
ObjectFactory *GetFactory() const
|
|
{
|
|
return factory_;
|
|
}
|
|
|
|
bool Initialize() override;
|
|
|
|
bool InitializeFinish() override;
|
|
void UninitializeThreads() override {}
|
|
void PreStartup() override {}
|
|
void PreZygoteFork() override {}
|
|
void PostZygoteFork() override {}
|
|
void InitializeGC() override {}
|
|
void StartGC() override {}
|
|
void StopGC() override {}
|
|
|
|
void VisitVmRoots([[maybe_unused]] const GCRootVisitor &visitor) override {}
|
|
void UpdateVmRefs() override {}
|
|
|
|
PandaVMType GetPandaVMType() const override
|
|
{
|
|
return PandaVMType::ECMA_VM;
|
|
}
|
|
|
|
LanguageContext GetLanguageContext() const override
|
|
{
|
|
return Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ECMASCRIPT);
|
|
}
|
|
|
|
panda::mem::HeapManager *GetHeapManager() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
panda::mem::GC *GetGC() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
panda::mem::GCTrigger *GetGCTrigger() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
StringTable *GetStringTable() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
panda::mem::GCStats *GetGCStats() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
panda::mem::MemStatsType *GetMemStats() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
GCStats *GetEcmaGCStats() const
|
|
{
|
|
return gcStats_;
|
|
}
|
|
|
|
panda::mem::GlobalObjectStorage *GetGlobalObjectStorage() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
MonitorPool *GetMonitorPool() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ThreadManager *GetThreadManager() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ManagedThread *GetAssociatedThread() const override
|
|
{
|
|
return thread_;
|
|
}
|
|
|
|
JSThread *GetAssociatedJSThread() const
|
|
{
|
|
return thread_;
|
|
}
|
|
|
|
CompilerInterface *GetCompiler() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
Rendezvous *GetRendezvous() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ObjectHeader *GetOOMErrorObject() override
|
|
{
|
|
// preallocated OOM is not implemented for JS
|
|
UNREACHABLE();
|
|
}
|
|
|
|
panda::mem::ReferenceProcessor *GetReferenceProcessor() const override
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
const RuntimeOptions &GetOptions() const override
|
|
{
|
|
return Runtime::GetOptions();
|
|
}
|
|
|
|
const JSRuntimeOptions &GetJSOptions() const
|
|
{
|
|
return options_;
|
|
}
|
|
|
|
JSHandle<GlobalEnv> GetGlobalEnv() const;
|
|
|
|
JSHandle<job::MicroJobQueue> GetMicroJobQueue() const;
|
|
|
|
bool ExecutePromisePendingJob() const;
|
|
|
|
RegExpParserCache *GetRegExpParserCache() const
|
|
{
|
|
ASSERT(regExpParserCache_ != nullptr);
|
|
return regExpParserCache_;
|
|
}
|
|
|
|
JSMethod *GetMethodForNativeFunction(const void *func);
|
|
|
|
EcmaStringTable *GetEcmaStringTable() const
|
|
{
|
|
ASSERT(stringTable_ != nullptr);
|
|
return stringTable_;
|
|
}
|
|
|
|
JSThread *GetJSThread() const
|
|
{
|
|
#if defined(ECMASCRIPT_ENABLE_THREAD_CHECK) && ECMASCRIPT_ENABLE_THREAD_CHECK
|
|
// Exclude GC thread
|
|
if (options_.IsEnableThreadCheck()) {
|
|
if (!Taskpool::GetCurrentTaskpool()->IsInThreadPool(std::this_thread::get_id()) &&
|
|
thread_->GetThreadId() != JSThread::GetCurrentThreadId()) {
|
|
LOG(FATAL, RUNTIME) << "Fatal: ecma_vm cannot run in multi-thread!";
|
|
}
|
|
}
|
|
#endif
|
|
return thread_;
|
|
}
|
|
|
|
JSThread *GetJSThreadNoCheck() const
|
|
{
|
|
return thread_;
|
|
}
|
|
|
|
bool ICEnable() const
|
|
{
|
|
return icEnable_;
|
|
}
|
|
|
|
void PushToNativePointerList(JSNativePointer *array);
|
|
void RemoveFromNativePointerList(JSNativePointer *array);
|
|
|
|
JSHandle<ecmascript::JSTaggedValue> GetAndClearEcmaUncaughtException() const;
|
|
JSHandle<ecmascript::JSTaggedValue> GetEcmaUncaughtException() const;
|
|
void EnableUserUncaughtErrorHandler();
|
|
|
|
EcmaRuntimeStat *GetRuntimeStat() const
|
|
{
|
|
return runtimeStat_;
|
|
}
|
|
|
|
void SetRuntimeStatEnable(bool flag);
|
|
|
|
bool IsRuntimeStatEnabled() const
|
|
{
|
|
return runtimeStatEnabled_;
|
|
}
|
|
|
|
bool IsOptionalLogEnabled() const
|
|
{
|
|
return optionalLogEnabled_;
|
|
}
|
|
|
|
void Iterate(const RootVisitor &v);
|
|
|
|
const Heap *GetHeap() const
|
|
{
|
|
return heap_;
|
|
}
|
|
|
|
void CollectGarbage(TriggerGCType gcType) const;
|
|
|
|
void StartHeapTracking(HeapTracker *tracker);
|
|
|
|
void StopHeapTracking();
|
|
|
|
NativeAreaAllocator *GetNativeAreaAllocator() const
|
|
{
|
|
return nativeAreaAllocator_.get();
|
|
}
|
|
|
|
HeapRegionAllocator *GetHeapRegionAllocator() const
|
|
{
|
|
return heapRegionAllocator_.get();
|
|
}
|
|
|
|
Chunk *GetChunk() const
|
|
{
|
|
return const_cast<Chunk *>(&chunk_);
|
|
}
|
|
void ProcessNativeDelete(const WeakRootVisitor &v0);
|
|
void ProcessReferences(const WeakRootVisitor &v0);
|
|
|
|
ModuleManager *GetModuleManager() const
|
|
{
|
|
return moduleManager_;
|
|
}
|
|
|
|
TSLoader *GetTSLoader() const
|
|
{
|
|
return tsLoader_;
|
|
}
|
|
|
|
void LoadStubs();
|
|
void SetupRegExpResultCache();
|
|
|
|
JSHandle<JSTaggedValue> GetRegExpCache() const
|
|
{
|
|
return JSHandle<JSTaggedValue>(reinterpret_cast<uintptr_t>(®expCache_));
|
|
}
|
|
|
|
void SetRegExpCache(JSTaggedValue newCache)
|
|
{
|
|
regexpCache_ = newCache;
|
|
}
|
|
|
|
tooling::NotificationManager *GetNotificationManager() const
|
|
{
|
|
return notificationManager_;
|
|
}
|
|
|
|
tooling::JsDebuggerManager *GetJsDebuggerManager() const
|
|
{
|
|
return debuggerManager_;
|
|
}
|
|
|
|
void SetEnableForceGC(bool enable)
|
|
{
|
|
options_.SetEnableForceGC(enable);
|
|
}
|
|
|
|
void SetData(void* data)
|
|
{
|
|
data_ = data;
|
|
}
|
|
|
|
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 SetConstpool(const JSPandaFile *jsPandaFile, JSTaggedValue constpool);
|
|
|
|
JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile);
|
|
|
|
void TryLoadSnapshotFile();
|
|
|
|
protected:
|
|
bool CheckEntrypointSignature([[maybe_unused]] Method *entrypoint) override
|
|
{
|
|
// unused interface
|
|
UNREACHABLE();
|
|
}
|
|
|
|
Expected<int, Runtime::Error> InvokeEntrypointImpl([[maybe_unused]] Method *entrypoint,
|
|
[[maybe_unused]] const std::vector<std::string> &args) override
|
|
{
|
|
// unused interface
|
|
UNREACHABLE();
|
|
}
|
|
|
|
void HandleUncaughtException(ObjectHeader *exception) override;
|
|
|
|
void PrintJSErrorInfo(const JSHandle<JSTaggedValue> &exceptionInfo);
|
|
|
|
private:
|
|
class CpuProfilingScope {
|
|
public:
|
|
explicit CpuProfilingScope(EcmaVM* vm);
|
|
~CpuProfilingScope();
|
|
|
|
private:
|
|
EcmaVM* vm_;
|
|
CpuProfiler* profiler_;
|
|
};
|
|
void SetGlobalEnv(GlobalEnv *global);
|
|
|
|
void SetMicroJobQueue(job::MicroJobQueue *queue);
|
|
|
|
Expected<JSTaggedValue, bool> InvokeEcmaEntrypoint(const JSPandaFile *jsPandaFile);
|
|
|
|
JSTaggedValue InvokeEcmaAotEntrypoint();
|
|
|
|
void InitializeEcmaScriptRunStat();
|
|
|
|
bool VerifyFilePath(const CString &filePath) const;
|
|
|
|
void ClearBufferData();
|
|
|
|
void ClearNativeMethodsData();
|
|
|
|
void LoadAOTFile(const std::string &fileName);
|
|
|
|
NO_MOVE_SEMANTIC(EcmaVM);
|
|
NO_COPY_SEMANTIC(EcmaVM);
|
|
|
|
// VM startup states.
|
|
JSRuntimeOptions options_;
|
|
bool icEnable_ {true};
|
|
bool vmInitialized_ {false};
|
|
GCStats *gcStats_ {nullptr};
|
|
bool snapshotSerializeEnable_ {false};
|
|
bool snapshotDeserializeEnable_ {false};
|
|
bool isUncaughtExceptionRegistered_ {false};
|
|
|
|
// VM memory management.
|
|
EcmaStringTable *stringTable_ {nullptr};
|
|
std::unique_ptr<NativeAreaAllocator> nativeAreaAllocator_;
|
|
std::unique_ptr<HeapRegionAllocator> heapRegionAllocator_;
|
|
Chunk chunk_;
|
|
Heap *heap_ {nullptr};
|
|
ObjectFactory *factory_ {nullptr};
|
|
ChunkVector<JSNativePointer *> nativePointerList_;
|
|
|
|
// VM execution states.
|
|
JSThread *thread_ {nullptr};
|
|
RegExpParserCache *regExpParserCache_ {nullptr};
|
|
JSTaggedValue globalEnv_ {JSTaggedValue::Hole()};
|
|
JSTaggedValue regexpCache_ {JSTaggedValue::Hole()};
|
|
JSTaggedValue microJobQueue_ {JSTaggedValue::Hole()};
|
|
bool runtimeStatEnabled_ {false};
|
|
EcmaRuntimeStat *runtimeStat_ {nullptr};
|
|
|
|
// For framewrok file snapshot.
|
|
CString snapshotFileName_;
|
|
CString frameworkAbcFileName_;
|
|
JSTaggedValue frameworkProgram_ {JSTaggedValue::Hole()};
|
|
const JSPandaFile *frameworkPandaFile_ {nullptr};
|
|
CMap<const JSPandaFile *, JSTaggedValue> cachedConstpools_ {};
|
|
|
|
// VM resources.
|
|
ChunkVector<JSMethod *> nativeMethods_;
|
|
ModuleManager *moduleManager_ {nullptr};
|
|
TSLoader *tsLoader_ {nullptr};
|
|
bool optionalLogEnabled_ {false};
|
|
AotCodeInfo *aotInfo_ {nullptr};
|
|
|
|
// Debugger
|
|
tooling::NotificationManager *notificationManager_ {nullptr};
|
|
tooling::JsDebuggerManager *debuggerManager_ {nullptr};
|
|
|
|
// Registered Callbacks
|
|
PromiseRejectCallback promiseRejectCallback_ {nullptr};
|
|
HostPromiseRejectionTracker hostPromiseRejectionTracker_ {nullptr};
|
|
void* data_ {nullptr};
|
|
|
|
friend class SnapShotSerialize;
|
|
friend class ObjectFactory;
|
|
friend class ValueSerializer;
|
|
friend class panda::JSNApi;
|
|
friend class JSPandaFileExecutor;
|
|
};
|
|
} // namespace ecmascript
|
|
} // namespace panda
|
|
|
|
#endif
|