• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 
16 #ifndef ECMASCRIPT_ECMA_VM_H
17 #define ECMASCRIPT_ECMA_VM_H
18 
19 #include <mutex>
20 
21 #include "ecmascript/base/config.h"
22 #include "ecmascript/builtins/builtins_method_index.h"
23 #include "ecmascript/ecma_context.h"
24 #include "ecmascript/js_runtime_options.h"
25 #include "ecmascript/js_thread.h"
26 #include "ecmascript/mem/c_containers.h"
27 #include "ecmascript/mem/c_string.h"
28 #include "ecmascript/mem/gc_stats.h"
29 #include "ecmascript/napi/include/dfx_jsnapi.h"
30 #include "ecmascript/napi/include/jsnapi.h"
31 #include "ecmascript/taskpool/taskpool.h"
32 
33 namespace panda {
34 class JSNApi;
35 namespace panda_file {
36 class File;
37 }  // namespace panda_file
38 
39 namespace ecmascript {
40 class GlobalEnv;
41 class ObjectFactory;
42 class RegExpParserCache;
43 class EcmaRuntimeStat;
44 class Heap;
45 class HeapTracker;
46 class JSNativePointer;
47 class Program;
48 class GCStats;
49 class CpuProfiler;
50 class RegExpExecResultCache;
51 class JSPromise;
52 enum class PromiseRejectionEvent : uint8_t;
53 class JSPandaFileManager;
54 class JSPandaFile;
55 class EcmaStringTable;
56 class SnapshotEnv;
57 class SnapshotSerialize;
58 class SnapshotProcessor;
59 class PGOProfiler;
60 #if !WIN_OR_MAC_OR_IOS_PLATFORM
61 class HeapProfilerInterface;
62 class HeapProfiler;
63 #endif
64 namespace job {
65 class MicroJobQueue;
66 }  // namespace job
67 
68 namespace tooling {
69 class JsDebuggerManager;
70 }  // namespace tooling
71 
72 template<typename T>
73 class JSHandle;
74 class JSArrayBuffer;
75 class JSFunction;
76 class Program;
77 class TSManager;
78 class AOTFileManager;
79 class SlowRuntimeStub;
80 class RequireManager;
81 class QuickFixManager;
82 class ConstantPool;
83 class FunctionCallTimer;
84 class EcmaStringTable;
85 
86 using NativePtrGetter = void* (*)(void* info);
87 
88 using ResolveBufferCallback = std::function<bool(std::string dirPath, uint8_t **buff, size_t *buffSize)>;
89 using UnloadNativeModuleCallback = std::function<bool(const std::string &moduleKey)>;
90 class EcmaVM {
91 public:
92     static EcmaVM *Create(const JSRuntimeOptions &options, EcmaParamConfiguration &config);
93 
94     static bool Destroy(EcmaVM *vm);
95 
96     EcmaVM(JSRuntimeOptions options, EcmaParamConfiguration config);
97 
98     EcmaVM();
99 
100     ~EcmaVM();
101 
SetLoop(void * loop)102     void SetLoop(void *loop)
103     {
104         loop_ = loop;
105     }
106 
GetLoop()107     void *GetLoop() const
108     {
109         return loop_;
110     }
111 
IsInitialized()112     bool IsInitialized() const
113     {
114         return initialized_;
115     }
116 
GetFactory()117     ObjectFactory *GetFactory() const
118     {
119         return factory_;
120     }
121 
122     void InitializePGOProfiler();
123     void ResetPGOProfiler();
124 
125     bool IsEnablePGOProfiler() const;
126 
127     bool Initialize();
128 
GetEcmaGCStats()129     GCStats *GetEcmaGCStats() const
130     {
131         return gcStats_;
132     }
133 
GetAssociatedJSThread()134     JSThread *GetAssociatedJSThread() const
135     {
136         return thread_;
137     }
138 
GetJSOptions()139     JSRuntimeOptions &GetJSOptions()
140     {
141         return options_;
142     }
143 
GetEcmaParamConfiguration()144     const EcmaParamConfiguration &GetEcmaParamConfiguration() const
145     {
146         return ecmaParamConfiguration_;
147     }
148 
149     JSHandle<GlobalEnv> GetGlobalEnv() const;
150 
ConstCast(const EcmaVM * vm)151     static EcmaVM *ConstCast(const EcmaVM *vm)
152     {
153         return const_cast<EcmaVM *>(vm);
154     }
155 
CheckThread()156     void CheckThread() const
157     {
158         // Exclude GC thread
159         if (thread_ == nullptr) {
160             LOG_FULL(FATAL) << "Fatal: ecma_vm has been destructed! vm address is: " << this;
161         }
162         if (!Taskpool::GetCurrentTaskpool()->IsInThreadPool(std::this_thread::get_id()) &&
163             thread_->GetThreadId() != JSThread::GetCurrentThreadId() && !thread_->IsCrossThreadExecutionEnable()) {
164                 LOG_FULL(FATAL) << "Fatal: ecma_vm cannot run in multi-thread!"
165                                     << " thread:" << thread_->GetThreadId()
166                                     << " currentThread:" << JSThread::GetCurrentThreadId();
167         }
168     }
169 
GetJSThread()170     ARK_INLINE JSThread *GetJSThread() const
171     {
172         if (options_.EnableThreadCheck()) {
173             CheckThread();
174         }
175         return thread_;
176     }
177 
ICEnabled()178     bool ICEnabled() const
179     {
180         return icEnabled_;
181     }
182 
183     void PushToNativePointerList(JSNativePointer *array);
184     void RemoveFromNativePointerList(JSNativePointer *array);
185     void PushToDeregisterModuleList(CString module);
186     void RemoveFromDeregisterModuleList(CString module);
187     bool ContainInDeregisterModuleList(CString module);
188     JSHandle<ecmascript::JSTaggedValue> GetAndClearEcmaUncaughtException() const;
189     JSHandle<ecmascript::JSTaggedValue> GetEcmaUncaughtException() const;
IsOptionalLogEnabled()190     bool IsOptionalLogEnabled() const
191     {
192         return optionalLogEnabled_;
193     }
194 
195     void Iterate(const RootVisitor &v, const RootRangeVisitor &rv);
196 
GetHeap()197     const Heap *GetHeap() const
198     {
199         return heap_;
200     }
201     void CollectGarbage(TriggerGCType gcType, GCReason reason = GCReason::OTHER) const;
202 
GetNativeAreaAllocator()203     NativeAreaAllocator *GetNativeAreaAllocator() const
204     {
205         return nativeAreaAllocator_.get();
206     }
207 
GetHeapRegionAllocator()208     HeapRegionAllocator *GetHeapRegionAllocator() const
209     {
210         return heapRegionAllocator_.get();
211     }
212 
GetChunk()213     Chunk *GetChunk() const
214     {
215         return const_cast<Chunk *>(&chunk_);
216     }
217     void ProcessNativeDelete(const WeakRootVisitor &visitor);
218     void ProcessReferences(const WeakRootVisitor &visitor);
219 
GetSnapshotEnv()220     SnapshotEnv *GetSnapshotEnv() const
221     {
222         return snapshotEnv_;
223     }
224 
GetJsDebuggerManager()225     tooling::JsDebuggerManager *GetJsDebuggerManager() const
226     {
227         return debuggerManager_;
228     }
229 
SetEnableForceGC(bool enable)230     void SetEnableForceGC(bool enable)
231     {
232         options_.SetEnableForceGC(enable);
233     }
234 
SetNativePtrGetter(NativePtrGetter cb)235     void SetNativePtrGetter(NativePtrGetter cb)
236     {
237         nativePtrGetter_ = cb;
238     }
239 
GetNativePtrGetter()240     NativePtrGetter GetNativePtrGetter() const
241     {
242         return nativePtrGetter_;
243     }
244 
GetNativePointerListSize()245     size_t GetNativePointerListSize()
246     {
247         return nativePointerList_.size();
248     }
249 
SetResolveBufferCallback(ResolveBufferCallback cb)250     void SetResolveBufferCallback(ResolveBufferCallback cb)
251     {
252         resolveBufferCallback_ = cb;
253     }
254 
GetResolveBufferCallback()255     ResolveBufferCallback GetResolveBufferCallback() const
256     {
257         return resolveBufferCallback_;
258     }
259 
SetUnloadNativeModuleCallback(const UnloadNativeModuleCallback & cb)260     void SetUnloadNativeModuleCallback(const UnloadNativeModuleCallback &cb)
261     {
262         unloadNativeModuleCallback_ = cb;
263     }
264 
GetUnloadNativeModuleCallback()265     UnloadNativeModuleCallback GetUnloadNativeModuleCallback() const
266     {
267         return unloadNativeModuleCallback_;
268     }
269 
SetConcurrentCallback(ConcurrentCallback callback,void * data)270     void SetConcurrentCallback(ConcurrentCallback callback, void *data)
271     {
272         concurrentCallback_ = callback;
273         concurrentData_ = data;
274     }
275 
276     void TriggerConcurrentCallback(JSTaggedValue result, JSTaggedValue hint);
277 
278     void WorkersetInfo(EcmaVM *hostVm, EcmaVM *workerVm);
279 
280     EcmaVM *GetWorkerVm(uint32_t tid);
281 
282     bool DeleteWorker(EcmaVM *hostVm, EcmaVM *workerVm);
283 
284     bool SuspendWorkerVm(uint32_t tid);
285 
286     void ResumeWorkerVm(uint32_t tid);
287 
288     template<typename Callback>
EnumerateWorkerVm(Callback cb)289     void EnumerateWorkerVm(Callback cb)
290     {
291         // since there is a lock, so cannot mark function const
292         os::memory::LockHolder lock(mutex_);
293         for (const auto &item : workerList_) {
294             cb(item.second);
295         }
296     }
297 
IsWorkerThread()298     bool IsWorkerThread()
299     {
300         return options_.IsWorker();
301     }
302 
IsBundlePack()303     bool IsBundlePack() const
304     {
305         return isBundlePack_;
306     }
307 
SetIsBundlePack(bool value)308     void SetIsBundlePack(bool value)
309     {
310         isBundlePack_ = value;
311     }
312 
313 #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER)
314     void DeleteHeapProfile();
315     HeapProfilerInterface *GetHeapProfile();
316     HeapProfilerInterface *GetOrNewHeapProfile();
317     void StartHeapTracking();
318     void StopHeapTracking();
319 #endif
320 
EnableReportModuleResolvingFailure()321     bool EnableReportModuleResolvingFailure() const
322     {
323         return options_.EnableReportModuleResolvingFailure();
324     }
325 
SetAssetPath(const CString & assetPath)326     void SetAssetPath(const CString &assetPath)
327     {
328         assetPath_ = assetPath;
329     }
330 
GetAssetPath()331     CString GetAssetPath() const
332     {
333         return assetPath_;
334     }
335 
SetBundleName(const CString & bundleName)336     void SetBundleName(const CString &bundleName)
337     {
338         bundleName_ = bundleName;
339     }
340 
GetBundleName()341     CString GetBundleName() const
342     {
343         return bundleName_;
344     }
345 
SetModuleName(const CString & moduleName)346     void SetModuleName(const CString &moduleName)
347     {
348         moduleName_ = moduleName;
349     }
350 
GetModuleName()351     CString GetModuleName() const
352     {
353         return moduleName_;
354     }
355 
356 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
GetProfiler()357     CpuProfiler *GetProfiler() const
358     {
359         return profiler_;
360     }
361 
SetProfiler(CpuProfiler * profiler)362     void SetProfiler(CpuProfiler *profiler)
363     {
364         profiler_ = profiler;
365     }
366 #endif
367 
GetPGOProfiler()368     PGOProfiler *GetPGOProfiler() const
369     {
370         return pgoProfiler_;
371     }
372 
373     void PreFork();
374     void PostFork();
375 
376     // For Internal Native MethodLiteral.
377     JSTaggedValue GetMethodByIndex(MethodIndex idx);
378 
GetQuickFixManager()379     QuickFixManager *GetQuickFixManager() const
380     {
381         return quickFixManager_;
382     }
383 
384     JSTaggedValue FastCallAot(size_t actualNumArgs, JSTaggedType *args, const JSTaggedType *prevFp);
385 
386     void HandleUncaughtException(JSTaggedValue exception);
387     void DumpCallTimeInfo();
388 
GetCallTimer()389     FunctionCallTimer *GetCallTimer() const
390     {
391         return callTimer_;
392     }
393 
GetEcmaStringTable()394     EcmaStringTable *GetEcmaStringTable() const
395     {
396         ASSERT(stringTable_ != nullptr);
397         return stringTable_;
398     }
399 
IncreaseCallDepth()400     void IncreaseCallDepth()
401     {
402         callDepth_++;
403     }
404 
DecreaseCallDepth()405     void DecreaseCallDepth()
406     {
407         ASSERT(callDepth_ > 0);
408         callDepth_--;
409     }
410 
IsTopLevelCallDepth()411     bool IsTopLevelCallDepth()
412     {
413         return callDepth_ == 0;
414     }
415 
416 protected:
417 
418     void PrintJSErrorInfo(const JSHandle<JSTaggedValue> &exceptionInfo) const;
419 
420 private:
421     void ClearBufferData();
422     void CheckStartCpuProfiler();
423 
424     // For Internal Native MethodLiteral.
425     void GenerateInternalNativeMethods();
426 
427     NO_MOVE_SEMANTIC(EcmaVM);
428     NO_COPY_SEMANTIC(EcmaVM);
429 
430     // VM startup states.
431     JSRuntimeOptions options_;
432     bool icEnabled_ {true};
433     bool initialized_ {false};
434     GCStats *gcStats_ {nullptr};
435     EcmaStringTable *stringTable_;
436 
437     // VM memory management.
438     std::unique_ptr<NativeAreaAllocator> nativeAreaAllocator_;
439     std::unique_ptr<HeapRegionAllocator> heapRegionAllocator_;
440     Chunk chunk_;
441     Heap *heap_ {nullptr};
442     ObjectFactory *factory_ {nullptr};
443     CList<JSNativePointer *> nativePointerList_;
444     // VM execution states.
445     JSThread *thread_ {nullptr};
446 
447     // VM resources.
448     SnapshotEnv *snapshotEnv_ {nullptr};
449     bool optionalLogEnabled_ {false};
450     // Debugger
451     tooling::JsDebuggerManager *debuggerManager_ {nullptr};
452     // merge abc
453     bool isBundlePack_ {true}; // isBundle means app compile mode is JSBundle
454 #if !WIN_OR_MAC_OR_IOS_PLATFORM
455     HeapProfilerInterface *heapProfile_ {nullptr};
456 #endif
457     CString assetPath_;
458     CString bundleName_;
459     CString moduleName_;
460     CList<CString> deregisterModuleList_;
461     // Registered Callbacks
462     NativePtrGetter nativePtrGetter_ {nullptr};
463     void *loop_ {nullptr};
464 
465     // resolve path to get abc's buffer
466     ResolveBufferCallback resolveBufferCallback_ {nullptr};
467 
468     // delete the native module and dlclose so from NativeModuleManager
469     UnloadNativeModuleCallback unloadNativeModuleCallback_ {nullptr};
470 
471     // Concurrent taskpool callback and data
472     ConcurrentCallback concurrentCallback_ {nullptr};
473     void *concurrentData_ {nullptr};
474 
475     // vm parameter configurations
476     EcmaParamConfiguration ecmaParamConfiguration_;
477 #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
478     CpuProfiler *profiler_ {nullptr};
479 #endif
480     FunctionCallTimer *callTimer_ {nullptr};
481 
482     // For Native MethodLiteral
483     static void *InternalMethodTable[static_cast<uint8_t>(MethodIndex::METHOD_END)];
484     CVector<JSTaggedValue> internalNativeMethods_;
485 
486     // For repair patch.
487     QuickFixManager *quickFixManager_ {nullptr};
488 
489     // PGO Profiler
490     PGOProfiler *pgoProfiler_ {nullptr};
491     // c++ call js
492     size_t callDepth_ {0};
493 
494     friend class Snapshot;
495     friend class SnapshotProcessor;
496     friend class ObjectFactory;
497     friend class ValueSerializer;
498     friend class panda::JSNApi;
499     friend class JSPandaFileExecutor;
500     friend class EcmaContext;
501     CMap<uint32_t, EcmaVM *> workerList_ {};
502     os::memory::Mutex mutex_;
503 };
504 }  // namespace ecmascript
505 }  // namespace panda
506 
507 #endif
508