• 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 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 packageName;
44     std::string pos;
45     uintptr_t* nativePointer = nullptr;
46 };
47 struct ApiCheckContext {
48     NativeModuleManager* moduleManager;
49     EcmaVM* ecmaVm;
50     panda::Local<panda::StringRef>& moduleName;
51     panda::Local<panda::ObjectRef>& exportObj;
52     panda::EscapeLocalScope& scope;
53 };
54 }
55 using JsFrameInfo = panda::ecmascript::JsFrameInfo;
56 using DFXJSNApi = panda::DFXJSNApi;
57 using LocalScope = panda::LocalScope;
58 using JSNApi = panda::JSNApi;
59 using JSValueRef = panda::JSValueRef;
60 using JsiRuntimeCallInfo = panda::JsiRuntimeCallInfo;
61 using PropertyAttribute = panda::PropertyAttribute;
62 using NativePointerCallbackData = panda::NativePointerCallbackData;
63 using AsyncNativeCallbacksPack = panda::AsyncNativeCallbacksPack;
64 using TriggerGCTaskCallback = panda::TriggerGCTaskCallback;
65 using TriggerGCData = panda::TriggerGCData;
66 using ArkIdleMonitor = panda::ecmascript::ArkIdleMonitor;
67 
68 // indirect used by ace_engine and(or) ability_runtime
69 using panda::Local;
70 class NativeTimerCallbackInfo;
71 template <bool changeState = true>
72 panda::JSValueRef ArkNativeFunctionCallBack(JsiRuntimeCallInfo *runtimeInfo);
73 void NapiDefinePropertyInner(napi_env env,
74                              Local<panda::ObjectRef> &obj,
75                              NapiPropertyDescriptor &propertyDescriptor,
76                              Local<panda::JSValueRef> &propertyName,
77                              bool &result);
78 bool NapiDefineProperty(napi_env env, panda::Local<panda::ObjectRef> &obj, NapiPropertyDescriptor propertyDescriptor);
79 NAPI_EXPORT panda::Local<panda::JSValueRef> NapiValueToLocalValue(napi_value v);
80 NAPI_EXPORT napi_value LocalValueToLocalNapiValue(panda::Local<panda::JSValueRef> local);
81 #ifdef ENABLE_CONTAINER_SCOPE
82 void FunctionSetContainerId(const EcmaVM *vm, panda::Local<panda::JSValueRef> &local);
83 #endif
84 panda::Local<panda::JSValueRef> NapiDefineClass(napi_env env, const char* name, NapiNativeCallback callback,
85                                                 void* data, const NapiPropertyDescriptor* properties, size_t length);
86 Local<JSValueRef> NapiDefineSendableClass(napi_env env,
87                                           const char* name,
88                                           NapiNativeCallback callback,
89                                           void* data,
90                                           const NapiPropertyDescriptor* properties,
91                                           size_t propertiesLength,
92                                           napi_value parent);
93 panda::Local<panda::ObjectRef> NapiCreateSObjectWithProperties(napi_env env,
94                                                                size_t propertyCount,
95                                                                const NapiPropertyDescriptor* properties);
96 panda::Local<panda::ObjectRef> NapiCreateObjectWithProperties(napi_env env, size_t propertyCount,
97                                                               const napi_property_descriptor *properties,
98                                                               Local<panda::JSValueRef> *keys,
99                                                               panda::PropertyAttribute *attrs);
100 
101 enum class ForceExpandState : int32_t {
102     FINISH_COLD_START = 0,
103     START_HIGH_SENSITIVE,
104     FINISH_HIGH_SENSITIVE,
105 };
106 
107 enum class ModuleTypes : uint8_t {
108     NATIVE_MODULE = 0x01,
109     MODULE_INNER_FILE,
110     UNKNOWN
111 };
112 
113 class SerializationData {
114 public:
SerializationData()115     SerializationData() : data_(nullptr), size_(0) {}
116     ~SerializationData() = default;
117 
GetData()118     uint8_t* GetData() const
119     {
120         return data_.get();
121     }
GetSize()122     size_t GetSize() const
123     {
124         return size_;
125     }
126 
127 private:
128     struct DataDeleter {
operatorDataDeleter129         void operator()(uint8_t* p) const
130         {
131             free(p);
132         }
133     };
134 
135     std::unique_ptr<uint8_t, DataDeleter> data_;
136     size_t size_;
137 };
138 
139 class NAPI_EXPORT ArkNativeEngine : public NativeEngine {
140 friend struct MoudleNameLocker;
141 public:
142     // ArkNativeEngine constructor
143     ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorker = false);
144     // ArkNativeEngine destructor
145     ~ArkNativeEngine() override;
146 
GetEcmaVm()147     NAPI_EXPORT const EcmaVM* GetEcmaVm() const override
148     {
149         return vm_;
150     }
151 
152     void Loop(LoopMode mode, bool needSync = false) override;
153     void SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) override;
154     // For concurrent
155     bool InitTaskPoolThread(NativeEngine* engine, NapiConcurrentCallback callback) override;
156     bool InitTaskPoolThread(napi_env env, NapiConcurrentCallback callback) override;
157     bool InitTaskPoolFunc(napi_env env, napi_value func, void* taskInfo) override;
158     void ClearCurrentTaskInfo() override;
159     bool HasPendingJob() const override;
160     bool IsProfiling() const override;
161     bool IsExecutingPendingJob() const override;
162     void* GetCurrentTaskInfo() const override;
163     void TerminateExecution() const override;
164     void NotifyTaskBegin() const override;
165     void NotifyTaskFinished() const override;
166 
167     // judge_typedarray
168     bool NapiNewTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
169                            Local<panda::ArrayBufferRef> arrayBuf,
170                            size_t byte_offset, size_t length, napi_value* result) override;
171     bool NapiNewSendableTypedArray(const EcmaVM* vm, NativeTypedArrayType typedArrayType,
172                                    Local<panda::SendableArrayBufferRef> arrayBuf,
173                                    size_t byte_offset, size_t length, napi_value* result) override;
174     NativeTypedArrayType GetTypedArrayType(panda::Local<panda::TypedArrayRef> typedArray) override;
175     NativeTypedArrayType GetSendableTypedArrayType(panda::Local<panda::SendableTypedArrayRef> typedArray) override;
176     // Call function
177     napi_value CallFunction(napi_value thisVar,
178                             napi_value function,
179                             napi_value const* argv,
180                             size_t argc) override;
181     bool RunScriptPath(const char* path, bool checkPath = false) override;
182 
183     napi_value RunScriptBuffer(const char* path, std::vector<uint8_t>& buffer, bool isBundle,
184         bool needUpdate = false) override;
185     bool RunScriptBuffer(const std::string& path, uint8_t* buffer, size_t size, bool isBundle) override;
186 
187     // Run buffer script
188     napi_value RunBufferScript(std::vector<uint8_t>& buffer) override;
189     napi_value RunActor(uint8_t* buffer, size_t size, const char* descriptor,
190         char* entryPoint = nullptr, bool checkPath = false) override;
191     // Set lib path
192     NAPI_EXPORT void SetPackagePath(const std::string appLinPathKey, const std::vector<std::string>& packagePath);
193     napi_value CreateInstance(napi_value constructor, napi_value const* argv, size_t argc) override;
194 
195     // Create native reference
196     NativeReference* CreateReference(napi_value value, uint32_t initialRefcount, bool flag = false,
197         NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr,
198         size_t nativeBindingSize = 0) override;
199     NativeReference* CreateAsyncReference(napi_value value, uint32_t initialRefcount, bool flag = false,
200         NapiNativeFinalize callback = nullptr, void* data = nullptr, void* hint = nullptr) override;
201     napi_value CreatePromise(NativeDeferred** deferred) override;
202     void* CreateRuntime(bool isLimitedWorker = false) override;
203     panda::Local<panda::ObjectRef> LoadArkModule(const void *buffer, int32_t len, const std::string& fileName);
204     napi_value ValueToNapiValue(JSValueWrapper& value) override;
205     NAPI_EXPORT static napi_value ArkValueToNapiValue(napi_env env, Local<JSValueRef> value);
206 
207     std::string GetSourceCodeInfo(napi_value value, ErrorPos pos) override;
208 
209     NAPI_EXPORT bool ExecuteJsBin(const std::string& fileName, bool checkPath = false);
210     static bool IsValidPandaFile(const char* path);
211     static bool IsValidScriptBuffer(uint8_t* scriptBuffer, size_t bufferSize);
212     NAPI_EXPORT panda::Local<panda::ObjectRef> LoadModuleByName(const std::string& moduleName, bool isAppModule,
213         const std::string& param, const std::string& instanceName, void* instance, const std::string& path = "");
214 
215     void TriggerFatalException(panda::Local<panda::JSValueRef> exceptionValue) override;
216     bool AdjustExternalMemory(int64_t ChangeInBytes, int64_t* AdjustedValue) override;
217 
218     // Set jsdump thresholds
219     void SetJsDumpThresholds(size_t thresholds) override;
220 
221     // Set Appfreeze Filter
222     void SetAppFreezeFilterCallback(AppFreezeFilterCallback callback) override;
223 
224     // Detect performance to obtain cpuprofiler file
225     void StartCpuProfiler(const std::string& fileName = "") override;
226     void StopCpuProfiler() override;
227 
228     void ResumeVM() override;
229     bool SuspendVM() override;
230     bool IsSuspended() override;
231     bool CheckSafepoint() override;
232     bool SuspendVMById(uint32_t tid) override;
233     void ResumeVMById(uint32_t tid) override;
234 
235     // isVmMode means the internal class in vm is visible.
236     // isPrivate means the number and string is not visible.
237     void DumpHeapSnapshot(const std::string& path, bool isVmMode = true,
238         DumpFormat dumpFormat = DumpFormat::JSON, bool isPrivate = false, bool captureNumericValue = false) override;
239     void DumpHeapSnapshot(int& fd, bool isFullGC, const std::function<void(uint8_t)> &allback) 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<RefAsyncFinalizer> &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) 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);
GetPromiseRejectCallBackRef()316     NativeReference* GetPromiseRejectCallBackRef()
317     {
318         return promiseRejectCallbackRef_;
319     }
320 
RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback)321     void RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback) override
322     {
323         allPromiseRejectCallback_ = callback;
324     }
325 
SetPromiseRejectCallBackRef(NativeReference * rejectCallbackRef)326     void SetPromiseRejectCallBackRef(NativeReference* rejectCallbackRef) override
327     {
328         promiseRejectCallbackRef_ = rejectCallbackRef;
329     }
330 
GetConcurrentCallbackFunc()331     NapiConcurrentCallback GetConcurrentCallbackFunc()
332     {
333         return concurrentCallbackFunc_;
334     }
335 
GetCheckCallbackRef()336     NativeReference* GetCheckCallbackRef()
337     {
338         return checkCallbackRef_;
339     }
340 
SetCheckCallbackRef(NativeReference * checkCallbackRef)341     void SetCheckCallbackRef(NativeReference* checkCallbackRef) override
342     {
343         checkCallbackRef_ = checkCallbackRef;
344     }
345 
GetNapiUncaughtExceptionCallback()346     NapiUncaughtExceptionCallback GetNapiUncaughtExceptionCallback() override
347     {
348         return napiUncaughtExceptionCallback_;
349     }
350 
GetPromiseRejectCallback()351     void* GetPromiseRejectCallback() override
352     {
353         return reinterpret_cast<void*>(PromiseRejectCallback);
354     }
355 
356     void SetModuleName(panda::Local<panda::ObjectRef> &nativeObj, std::string moduleName);
357     void GetCurrentModuleInfo(std::string& moduleName, std::string& fileName, bool needRecordName) override;
358     bool GetIsBundle() override;
359     bool GetIsNormalizedOhmUrlPack() override;
360     bool GetIsDebugModeEnabled() override;
361     std::string GetBundleName() override;
362     std::string GetPkgName(const std::string &moduleName) override;
363     bool IsExecuteModuleInAbcFile(std::string bundleName, std::string moduleName, std::string ohmurl) override;
364     int GetProcessStartRealTime() override;
365     void PostLooperTriggerIdleGCTask();
366 
367     static bool napiProfilerEnabled;
368     static std::string tempModuleName_;
369 
370     static void* GetNativePtrCallBack(void* data);
371     static void CopyPropertyApiFilter(const std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker,
372         const EcmaVM* ecmaVm, const panda::Local<panda::ObjectRef> exportObj,
373         panda::Local<panda::ObjectRef>& exportCopy, const std::string& apiPath);
374 
IsCrossThreadCheckEnabled()375     inline bool IsCrossThreadCheckEnabled() const override
376     {
377         return crossThreadCheck_;
378     }
379     static constexpr size_t FINALIZERS_PACK_PENDING_NATIVE_BINDING_SIZE_THRESHOLD = 500 * 1024 * 1024;  // 500 MB
380 
GetTimerListHead()381     NativeTimerCallbackInfo* GetTimerListHead() const
382     {
383         return TimerListHead_;
384     }
SetTimerListHead(NativeTimerCallbackInfo * info)385     void SetTimerListHead(NativeTimerCallbackInfo* info)
386     {
387         TimerListHead_ = info;
388     }
389 
390 private:
GetNapiOptions()391     inline NapiOptions *GetNapiOptions() const override
392     {
393         return options_;
394     }
395 
396     static void RunCallbacks(ArkFinalizersPack *finalizersPack);
397     static void RunAsyncCallbacks(std::vector<RefAsyncFinalizer> *finalizers);
398     static void RunCallbacks(AsyncNativeCallbacksPack *callbacks);
399     static void RunCallbacks(TriggerGCData *triggerGCData);
400     static void SetAttribute(bool isLimitedWorker, panda::RuntimeOption &option);
401     static NativeEngine* CreateRuntimeFunc(NativeEngine* engine, void* jsEngine, bool isLimitedWorker = false);
402     static bool CheckArkApiAllowList(
403         NativeModule* module, panda::ecmascript::ApiCheckContext context, panda::Local<panda::ObjectRef>& exportCopy);
IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)404     void IncreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)
405     {
406         pendingFinalizersPackNativeBindingSize_ += nativeBindingSize;
407     }
DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)408     void DecreasePendingFinalizersPackNativeBindingSize(size_t nativeBindingSize)
409     {
410         pendingFinalizersPackNativeBindingSize_ -= nativeBindingSize;
411     }
412 
413     EcmaVM* vm_ = nullptr;
414     bool needStop_ = false;
415     panda::LocalScope topScope_;
416     NapiConcurrentCallback concurrentCallbackFunc_ { nullptr };
417     NativeReference* promiseRejectCallbackRef_ { nullptr };
418     NativeReference* checkCallbackRef_ { nullptr };
419     std::map<NativeModule*, panda::Global<panda::JSValueRef>> loadedModules_ {};
420     static PermissionCheckCallback permissionCheckCallback_;
421     NapiUncaughtExceptionCallback napiUncaughtExceptionCallback_ { nullptr };
422     NapiAllPromiseRejectCallback allPromiseRejectCallback_ {nullptr};
423     SourceMapCallback SourceMapCallback_ { nullptr };
424     static bool napiProfilerParamReaded;
425     bool isLimitedWorker_ = false;
426     size_t pendingFinalizersPackNativeBindingSize_ {0};
427     ArkFinalizersPack arkFinalizersPack_ {};
428     std::vector<RefAsyncFinalizer> pendingAsyncFinalizers_ {};
429     // napi options and its cache
430     NapiOptions* options_ { nullptr };
431     bool crossThreadCheck_ { false };
432     NativeTimerCallbackInfo* TimerListHead_ {nullptr};
433 };
434 #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_IMPL_ARK_ARK_NATIVE_ENGINE_H */
435