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