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 FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H 17 #define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H 18 19 #include <memory> 20 #if !defined(PREVIEW) && !defined(IOS_PLATFORM) 21 #include <sys/wait.h> 22 #include <sys/types.h> 23 #endif 24 #include <iostream> 25 #include <map> 26 #include <mutex> 27 #include <regex> 28 #include <thread> 29 #include <unistd.h> 30 31 #include "ark_idle_monitor.h" 32 #include "ark_native_options.h" 33 #include "ecmascript/napi/include/dfx_jsnapi.h" 34 #include "ecmascript/napi/include/jsnapi.h" 35 #include "native_engine/impl/ark/ark_finalizers_pack.h" 36 #include "native_engine/native_engine.h" 37 38 namespace panda::ecmascript { 39 struct JsHeapDumpWork; 40 struct JsFrameInfo { 41 std::string functionName; 42 std::string fileName; 43 std::string pos; 44 uintptr_t* nativePointer = nullptr; 45 }; 46 struct ApiCheckContext { 47 NativeModuleManager* moduleManager; 48 EcmaVM* ecmaVm; 49 panda::Local<panda::StringRef>& moduleName; 50 panda::Local<panda::ObjectRef>& exportObj; 51 panda::EscapeLocalScope& scope; 52 }; 53 } 54 using JsFrameInfo = panda::ecmascript::JsFrameInfo; 55 using DFXJSNApi = panda::DFXJSNApi; 56 using LocalScope = panda::LocalScope; 57 using JSNApi = panda::JSNApi; 58 using JSValueRef = panda::JSValueRef; 59 using JsiRuntimeCallInfo = panda::JsiRuntimeCallInfo; 60 using PropertyAttribute = panda::PropertyAttribute; 61 using NativePointerCallbackData = panda::NativePointerCallbackData; 62 using AsyncNativeCallbacksPack = panda::AsyncNativeCallbacksPack; 63 using TriggerGCTaskCallback = panda::TriggerGCTaskCallback; 64 using TriggerGCData = panda::TriggerGCData; 65 using ArkIdleMonitor = panda::ecmascript::ArkIdleMonitor; 66 67 // indirect used by ace_engine and(or) ability_runtime 68 using panda::Local; 69 70 template <bool changeState = true> 71 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo); 72 void NapiDefinePropertyInner(napi_env env, 73 Local<panda::ObjectRef> &obj, 74 NapiPropertyDescriptor &propertyDescriptor, 75 Local<panda::JSValueRef> &propertyName, 76 bool &result); 77 bool NapiDefineProperty(napi_env env, panda::Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor); 78 NAPI_EXPORT panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v); 79 NAPI_EXPORT napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local); 80 #ifdef ENABLE_CONTAINER_SCOPE 81 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &local); 82 #endif 83 #if !defined(is_arkui_x) && defined(OHOS_PLATFORM) 84 std::string DumpHybridStack(const EcmaVM* vm); 85 #endif 86 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback, 87 void* data, const NapiPropertyDescriptor* properties, size_t length); 88 Local<JSValueRef> NapiDefineSendableClass(napi_env env, 89 const char* name, 90 NapiNativeCallback callback, 91 void* data, 92 const NapiPropertyDescriptor* properties, 93 size_t propertiesLength, 94 napi_value parent); 95 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env, 96 size_t propertyCount, 97 const NapiPropertyDescriptor* properties); 98 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount, 99 const napi_property_descriptor *properties, 100 Local<panda::JSValueRef> *keys, 101 panda::PropertyAttribute *attrs); 102 103 enum class ForceExpandState : int32_t { 104 FINISH_COLD_START = 0, 105 START_HIGH_SENSITIVE, 106 FINISH_HIGH_SENSITIVE, 107 }; 108 109 enum class ModuleTypes : uint8_t { 110 NATIVE_MODULE = 0x01, 111 MODULE_INNER_FILE, 112 UNKNOWN 113 }; 114 115 class SerializationData { 116 public: SerializationData()117 SerializationData() : data_(nullptr), size_(0) {} 118 ~SerializationData() = default; 119 GetData()120 uint8_t* GetData() const 121 { 122 return data_.get(); 123 } GetSize()124 size_t GetSize() const 125 { 126 return size_; 127 } 128 129 private: 130 struct DataDeleter { operatorDataDeleter131 void operator()(uint8_t* p) const 132 { 133 free(p); 134 } 135 }; 136 137 std::unique_ptr<uint8_t, DataDeleter> data_; 138 size_t size_; 139 }; 140 141 class NAPI_EXPORT ArkNativeEngine : public NativeEngine { 142 friend struct MoudleNameLocker; 143 public: 144 // ArkNativeEngine constructor 145 ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker = false); 146 // ArkNativeEngine destructor 147 ~ArkNativeEngine() override; 148 GetEcmaVm()149 NAPI_EXPORT const EcmaVM* GetEcmaVm() const override 150 { 151 return vm_; 152 } 153 154 void Loop(LoopMode mode, bool needSync = false) override; 155 void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) override; 156 // For concurrent 157 bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) override; 158 bool InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback) override; 159 bool InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo) override; 160 void ClearCurrentTaskInfo() override; 161 bool HasPendingJob() const override; 162 bool IsProfiling() const override; 163 bool IsExecutingPendingJob() const override; 164 void* GetCurrentTaskInfo() const override; 165 void TerminateExecution() const override; 166 void NotifyTaskBegin() const override; 167 void NotifyTaskFinished() const override; 168 169 // judge_typedarray 170 bool NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, 171 Local<panda::ArrayBufferRef> arrayBuf, 172 size_t byte_offset, size_t length, napi_value* result) override; 173 bool NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType, 174 Local<panda::SendableArrayBufferRef> arrayBuf, 175 size_t byte_offset, size_t length, napi_value* result) override; 176 NativeTypedArrayType GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray) override; 177 NativeTypedArrayType GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray) override; 178 // Call function 179 napi_value CallFunction(napi_value thisVar, 180 napi_value function, 181 napi_value const* argv, 182 size_t argc) override; 183 bool RunScriptPath(const char* path, bool checkPath = false) override; 184 185 napi_value RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle) override; 186 bool RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle) override; 187 188 // Run buffer script 189 napi_value RunBufferScript(std::vector<uint8_t>& buffer) override; 190 napi_value RunActor(uint8_t* buffer, size_t size, const char* descriptor, 191 char* entryPoint = nullptr, bool checkPath = false) override; 192 // Set lib path 193 NAPI_EXPORT void SetPackagePath(const std::string appLinPathKey, const std::vector<std::string>& packagePath); 194 napi_value CreateInstance(napi_value constructor, napi_value const* argv, size_t argc) override; 195 196 // Create native reference 197 NativeReference* CreateReference(napi_value value, uint32_t initialRefcount, bool flag = false, 198 NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr, 199 size_t nativeBindingSize = 0) override; 200 NativeReference* CreateAsyncReference(napi_value value, uint32_t initialRefcount, bool flag = false, 201 NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) override; 202 napi_value CreatePromise(NativeDeferred** deferred) override; 203 void* CreateRuntime(bool isLimitedWorker = false) override; 204 panda::Local<panda::ObjectRef> LoadArkModule(const void* buffer, int32_t len, const std::string& fileName); 205 napi_value ValueToNapiValue(JSValueWrapper& value) override; 206 NAPI_EXPORT static napi_value ArkValueToNapiValue(napi_env env, Local<JSValueRef> value); 207 208 std::string GetSourceCodeInfo(napi_value value, ErrorPos pos) override; 209 210 NAPI_EXPORT bool ExecuteJsBin(const std::string& fileName, bool checkPath = false); 211 static bool IsValidPandaFile(const char* path); 212 static bool IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize); 213 NAPI_EXPORT panda::Local<panda::ObjectRef> LoadModuleByName(const std::string& moduleName, bool isAppModule, 214 const std::string& param, const std::string& instanceName, void* instance, const std::string& path = ""); 215 216 void TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue) override; 217 bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) override; 218 219 // Set jsdump thresholds 220 void SetJsDumpThresholds(size_t thresholds) override; 221 222 // Set Appfreeze Filter 223 void SetAppFreezeFilterCallback(AppFreezeFilterCallback callback) override; 224 225 // Detect performance to obtain cpuprofiler file 226 void StartCpuProfiler(const std::string& fileName = "") override; 227 void StopCpuProfiler() override; 228 229 void ResumeVM() override; 230 bool SuspendVM() override; 231 bool IsSuspended() override; 232 bool CheckSafepoint() override; 233 bool SuspendVMById(uint32_t tid) override; 234 void ResumeVMById(uint32_t tid) override; 235 236 // isVmMode means the internal class in vm is visible. 237 // isPrivate means the number and string is not visible. 238 void DumpHeapSnapshot(const std::string& path, bool isVmMode = true, 239 DumpFormat dumpFormat = DumpFormat::JSON, bool isPrivate = false, bool captureNumericValue = false) override; 240 void DumpCpuProfile() override; 241 // Dump the file into faultlog for heap leak. 242 void DumpHeapSnapshot(bool isVmMode = true, DumpFormat dumpFormat = DumpFormat::JSON, 243 bool isPrivate = false, bool isFullGC = true) override; 244 bool BuildNativeAndJsStackTrace(std::string& stackTraceStr) override; 245 bool BuildJsStackTrace(std::string& stackTraceStr) override; 246 bool BuildJsStackInfoListWithCustomDepth(std::vector<JsFrameInfo>& jsFrames) 247 override; 248 249 bool DeleteWorker(NativeEngine* workerEngine) override; 250 bool StartHeapTracking(double timeInterval, bool isVmMode = true) override; 251 bool StopHeapTracking(const std::string& filePath) override; 252 253 void PrintStatisticResult() override; 254 void StartRuntimeStat() override; 255 void StopRuntimeStat() override; 256 size_t GetArrayBufferSize() override; 257 size_t GetHeapTotalSize() override; 258 size_t GetHeapUsedSize() override; 259 size_t GetHeapObjectSize() override; 260 size_t GetHeapLimitSize() override; 261 size_t GetProcessHeapLimitSize() override; 262 size_t GetGCCount() override; 263 size_t GetGCDuration() override; 264 size_t GetAccumulatedAllocateSize() override; 265 size_t GetAccumulatedFreeSize() override; 266 size_t GetFullGCLongTimeCount() override; 267 void NotifyApplicationState(bool inBackground) override; 268 void NotifyIdleStatusControl(std::function<void(bool)> callback) override; 269 void NotifyIdleTime(int idleMicroSec) override; 270 void NotifyMemoryPressure(bool inHighMemoryPressure = false) override; 271 void NotifyForceExpandState(int32_t value) override; 272 273 void AllowCrossThreadExecution() const override; 274 static void PromiseRejectCallback(void* values); 275 276 void SetMockModuleList(const std::map<std::string, std::string> &list) override; 277 int32_t GetObjectHash(napi_env env, napi_value src) override; 278 279 // debugger 280 bool IsMixedDebugEnabled(); 281 void JsHeapStart(); 282 uint64_t GetCurrentTickMillseconds(); 283 bool JudgmentDumpExecuteTask(int pid); 284 void JudgmentDump(size_t limitSize); 285 void NotifyNativeCalling(const void *nativeAddress); 286 287 void PostFinalizeTasks(); 288 void PostAsyncTask(AsyncNativeCallbacksPack *callbacksPack); 289 void PostTriggerGCTask(TriggerGCData& data); 290 GetArkFinalizersPack()291 ArkFinalizersPack &GetArkFinalizersPack() 292 { 293 return arkFinalizersPack_; 294 } 295 GetPendingAsyncFinalizers()296 std::vector<RefFinalizer> &GetPendingAsyncFinalizers() 297 { 298 return pendingAsyncFinalizers_; 299 } 300 301 void RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) override; 302 void HandleUncaughtException() override; 303 bool HasPendingException() override; 304 void RegisterPermissionCheck(PermissionCheckCallback callback) override; 305 bool ExecutePermissionCheck() override; 306 void RegisterTranslateBySourceMap(SourceMapCallback callback) override; 307 std::string ExecuteTranslateBySourceMap(const std::string& rawStack) override; 308 void RegisterSourceMapTranslateCallback(SourceMapTranslateCallback callback) override; 309 panda::Local<panda::ObjectRef> GetModuleFromName( 310 const std::string& moduleName, bool isAppModule, const std::string& id, const std::string& param, 311 const std::string& instanceName, void** instance); 312 napi_value NapiLoadModule(const char* path, const char* module_info) override; 313 napi_value NapiLoadModuleWithInfo(const char* path, const char* module_info) override; 314 std::string GetOhmurl(std::string str); 315 Local<JSValueRef> NapiLoadNativeModule(std::string path); 316 ModuleTypes CheckLoadType(const std::string &path); GetPromiseRejectCallBackRef()317 NativeReference* GetPromiseRejectCallBackRef() 318 { 319 return promiseRejectCallbackRef_; 320 } 321 SetPromiseRejectCallBackRef(NativeReference * rejectCallbackRef)322 void SetPromiseRejectCallBackRef(NativeReference* rejectCallbackRef) override 323 { 324 promiseRejectCallbackRef_ = rejectCallbackRef; 325 } 326 GetConcurrentCallbackFunc()327 NapiConcurrentCallback GetConcurrentCallbackFunc() 328 { 329 return concurrentCallbackFunc_; 330 } 331 GetCheckCallbackRef()332 NativeReference* GetCheckCallbackRef() 333 { 334 return checkCallbackRef_; 335 } 336 SetCheckCallbackRef(NativeReference * checkCallbackRef)337 void SetCheckCallbackRef(NativeReference* checkCallbackRef) override 338 { 339 checkCallbackRef_ = checkCallbackRef; 340 } 341 GetNapiUncaughtExceptionCallback()342 NapiUncaughtExceptionCallback GetNapiUncaughtExceptionCallback() override 343 { 344 return napiUncaughtExceptionCallback_; 345 } 346 GetPromiseRejectCallback()347 void* GetPromiseRejectCallback() override 348 { 349 return reinterpret_cast<void*>(PromiseRejectCallback); 350 } 351 352 void SetModuleName(panda::Local<panda::ObjectRef> &nativeObj, std::string moduleName); 353 void GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName) override; 354 bool GetIsBundle() override; 355 bool GetIsNormalizedOhmUrlPack() override; 356 bool GetIsDebugModeEnabled() override; 357 std::string GetBundleName() override; 358 std::string GetPkgName(const std::string &moduleName) override; 359 bool IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl) override; 360 int GetProcessStartRealTime() override; 361 void PostLooperTriggerIdleGCTask(); 362 363 static bool napiProfilerEnabled; 364 static std::string tempModuleName_; 365 366 static void* GetNativePtrCallBack(void* data); 367 static void CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, 368 const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj, 369 panda::Local<panda::ObjectRef>& exportCopy, const std::string& apiPath); 370 IsCrossThreadCheckEnabled()371 inline bool IsCrossThreadCheckEnabled() const override 372 { 373 return crossThreadCheck_; 374 } 375 static constexpr size_t FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD = 500 * 1024 * 1024; // 500 MB 376 377 private: GetNapiOptions()378 inline NapiOptions *GetNapiOptions() const override 379 { 380 return options_; 381 } 382 383 static void RunCallbacks(ArkFinalizersPack *finalizersPack); 384 static void RunAsyncCallbacks(std::vector<RefFinalizer> *finalizers); 385 static void RunCallbacks(AsyncNativeCallbacksPack *callbacks); 386 static void RunCallbacks(TriggerGCData *triggerGCData); 387 static void SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option); 388 static NativeEngine* CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker = false); 389 static bool CheckArkApiAllowList( 390 NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy); IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)391 void IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize) 392 { 393 pendingFinalizersPackNativeBindingSize_ += nativeBindingSize; 394 } DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)395 void DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize) 396 { 397 pendingFinalizersPackNativeBindingSize_ -= nativeBindingSize; 398 } 399 400 EcmaVM* vm_ = nullptr; 401 bool needStop_ = false; 402 panda::LocalScope topScope_; 403 NapiConcurrentCallback concurrentCallbackFunc_ { nullptr }; 404 NativeReference* promiseRejectCallbackRef_ { nullptr }; 405 NativeReference* checkCallbackRef_ { nullptr }; 406 std::map<NativeModule*, panda::Global<panda::JSValueRef>> loadedModules_ {}; 407 static PermissionCheckCallback permissionCheckCallback_; 408 NapiUncaughtExceptionCallback napiUncaughtExceptionCallback_ { nullptr }; 409 SourceMapCallback SourceMapCallback_ { nullptr }; 410 static bool napiProfilerParamReaded; 411 bool isLimitedWorker_ = false; 412 size_t pendingFinalizersPackNativeBindingSize_ {0}; 413 ArkFinalizersPack arkFinalizersPack_ {}; 414 std::vector<RefFinalizer> pendingAsyncFinalizers_ {}; 415 // napi options and its cache 416 NapiOptions* options_ { nullptr }; 417 bool crossThreadCheck_ { false }; 418 std::shared_ptr<ArkIdleMonitor> arkIdleMonitor_; 419 }; 420 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H */ 421