From b50dfe28143520f49a6b77640717bc5a124e96d7 Mon Sep 17 00:00:00 2001 From: zhaoziming Date: Sun, 8 Jun 2025 01:43:33 +0800 Subject: [PATCH] Isolate napi_ref for cross reference Issue: https://gitee.com/openharmony/arkui_napi/issues/ICDFKS Signed-off-by: zhaoziming Change-Id: I9183b2a8568e96fba704429aac098921d1a8e14b --- native_engine/impl/ark/ark_native_engine.cpp | 4 +- .../impl/ark/ark_native_reference.cpp | 83 ++++++++++++------- native_engine/impl/ark/ark_native_reference.h | 44 +++++++--- 3 files changed, 87 insertions(+), 44 deletions(-) diff --git a/native_engine/impl/ark/ark_native_engine.cpp b/native_engine/impl/ark/ark_native_engine.cpp index 9a57ddee7..a4d6b8315 100644 --- a/native_engine/impl/ark/ark_native_engine.cpp +++ b/native_engine/impl/ark/ark_native_engine.cpp @@ -1828,8 +1828,8 @@ NativeReference* ArkNativeEngine::CreateReference(napi_value value, uint32_t ini NativeReference* ArkNativeEngine::CreateXRefReference(napi_value value, uint32_t initialRefcount, bool flag, NapiNativeFinalize callback, void* data) { - ArkNativeReferenceConfig config(initialRefcount, true, flag, callback, data); - return new ArkNativeReference(this, value, config); + ArkNativeReferenceConfig config(initialRefcount, flag, callback, data); + return new ArkXRefNativeReference(this, value, config); } NativeReference* ArkNativeEngine::CreateAsyncReference(napi_value value, uint32_t initialRefcount, diff --git a/native_engine/impl/ark/ark_native_reference.cpp b/native_engine/impl/ark/ark_native_reference.cpp index 3bb53c556..ba6471739 100644 --- a/native_engine/impl/ark/ark_native_reference.cpp +++ b/native_engine/impl/ark/ark_native_reference.cpp @@ -40,23 +40,7 @@ ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, hint_(hint), nativeBindingSize_(nativeBindingSize) { - ArkNativeReferenceConstructor(); -} - -ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, - napi_value value, - ArkNativeReferenceConfig& config) - : engine_(engine), - ownership_(config.deleteSelf ? ReferenceOwnerShip::RUNTIME : ReferenceOwnerShip::USER), - value_(), - refCount_(config.initialRefcount), - isProxyReference_(config.isProxyReference), - deleteSelf_(config.deleteSelf), - napiCallback_(config.napiCallback), - data_(config.data) -{ - value_.CreateXRefGloablReference(engine->GetEcmaVm(), LocalValueFromJsValue(value)); - ArkNativeReferenceConstructor(); + ArkNativeReferenceConstructor(FreeGlobalCallBack); } ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, @@ -79,10 +63,10 @@ ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, hint_(hint), nativeBindingSize_(nativeBindingSize) { - ArkNativeReferenceConstructor(); + ArkNativeReferenceConstructor(FreeGlobalCallBack); } -void ArkNativeReference::ArkNativeReferenceConstructor() +void ArkNativeReference::ArkNativeReferenceConstructor(WeakRefClearCallBack weakCallback) { if (napiCallback_ != nullptr) { // Async callback will redirect to root engine, no monitoring needed. @@ -98,7 +82,7 @@ void ArkNativeReference::ArkNativeReferenceConstructor() } if (refCount_ == 0) { - value_.SetWeakCallback(reinterpret_cast(this), FreeGlobalCallBack, NativeFinalizeCallBack); + value_.SetWeakCallback(reinterpret_cast(this), weakCallback, NativeFinalizeCallBack); } if (ownership_ == ReferenceOwnerShip::RUNTIME) { @@ -129,11 +113,7 @@ ArkNativeReference::~ArkNativeReference() return; } hasDelete_ = true; - if (isProxyReference_) { - value_.FreeXRefGlobalHandleAddr(); - } else { - value_.FreeGlobalHandleAddr(); - } + value_.FreeGlobalHandleAddr(); FinalizeCallback(FinalizerState::DESTRUCTION); } @@ -279,11 +259,7 @@ void ArkNativeReference::FinalizeCallback(FinalizerState state) void ArkNativeReference::FreeGlobalCallBack(void* ref) { auto that = reinterpret_cast(ref); - if (that->isProxyReference_) { - that->value_.FreeXRefGlobalHandleAddr(); - } else { - that->value_.FreeGlobalHandleAddr(); - } + that->value_.FreeGlobalHandleAddr(); } void ArkNativeReference::NativeFinalizeCallBack(void* ref) @@ -340,3 +316,50 @@ bool ArkNativeReference::IsValidHeapObject() return value_.IsValidHeapObject(); } #endif // PANDA_JS_ETS_HYBRID_MODE + +ArkXRefNativeReference::ArkXRefNativeReference(ArkNativeEngine* engine, + napi_value value, + const ArkNativeReferenceConfig &config) + : ArkNativeReference(engine, config) +{ + value_.CreateXRefGloablReference(engine->GetEcmaVm(), LocalValueFromJsValue(value)); + ArkNativeReferenceConstructor(FreeXRefGlobalCallBack); +} + +ArkXRefNativeReference::~ArkXRefNativeReference() +{ + VALID_ENGINE_CHECK(engine_, engine_, engineId_); + + if (deleteSelf_ && engine_->GetReferenceManager()) { + engine_->GetReferenceManager()->ReleaseHandler(this); + prev_ = nullptr; + next_ = nullptr; + } + if (value_.IsEmpty()) { + return; + } + hasDelete_ = true; + value_.FreeXRefGlobalHandleAddr(); + FinalizeCallback(FinalizerState::DESTRUCTION); +} + +void ArkXRefNativeReference::FreeXRefGlobalCallBack(void* ref) +{ + auto that = reinterpret_cast(ref); + that->value_.FreeXRefGlobalHandleAddr(); +} + +uint32_t ArkXRefNativeReference::Unref() +{ + if (refCount_ == 0) { + return refCount_; + } + --refCount_; + if (value_.IsEmpty()) { + return refCount_; + } + if (refCount_ == 0) { + value_.SetWeakCallback(reinterpret_cast(this), FreeXRefGlobalCallBack, NativeFinalizeCallBack); + } + return refCount_; +} diff --git a/native_engine/impl/ark/ark_native_reference.h b/native_engine/impl/ark/ark_native_reference.h index 3bc67be78..4a8ff987c 100644 --- a/native_engine/impl/ark/ark_native_reference.h +++ b/native_engine/impl/ark/ark_native_reference.h @@ -41,23 +41,23 @@ enum class ReferenceOwnerShip : uint8_t { struct ArkNativeReferenceConfig { uint32_t initialRefcount; - bool isProxyReference; bool deleteSelf; NapiNativeFinalize napiCallback; void* data; - ArkNativeReferenceConfig(uint32_t initialRefcount, - bool isProxyReference, + explicit ArkNativeReferenceConfig(uint32_t initialRefcount, bool deleteSelf = false, NapiNativeFinalize napiCallback = nullptr, void* data = nullptr) : initialRefcount(initialRefcount), - isProxyReference(isProxyReference), deleteSelf(deleteSelf), napiCallback(napiCallback), - data(data) {} + data(data) + {} }; +using WeakRefClearCallBack = void (*)(void*); + class ArkNativeReference : public NativeReference { public: ArkNativeReference(ArkNativeEngine* engine, @@ -69,9 +69,6 @@ public: void* hint = nullptr, bool isAsyncCall = false, size_t nativeBindingSize = 0); - ArkNativeReference(ArkNativeEngine* engine, - napi_value value, - ArkNativeReferenceConfig &config); ArkNativeReference(ArkNativeEngine* engine, Local value, uint32_t initialRefcount, @@ -101,8 +98,19 @@ public: bool IsValidHeapObject(); #endif // PANDA_JS_ETS_HYBRID_MODE -private: - void ArkNativeReferenceConstructor(); +protected: + ArkNativeReference(ArkNativeEngine* engine, + const ArkNativeReferenceConfig &config) + : engine_(engine), + ownership_(config.deleteSelf ? ReferenceOwnerShip::RUNTIME : ReferenceOwnerShip::USER), + value_(), + refCount_(config.initialRefcount), + deleteSelf_(config.deleteSelf), + napiCallback_(config.napiCallback), + data_(config.data) + {} + + void ArkNativeReferenceConstructor(WeakRefClearCallBack weakCallback); ArkNativeEngine* engine_; uint64_t engineId_ {0}; @@ -110,7 +118,6 @@ private: Global value_; uint32_t refCount_ {0}; - bool isProxyReference_{false}; bool deleteSelf_ {false}; bool isAsyncCall_ {false}; @@ -129,9 +136,22 @@ private: void EnqueueAsyncTask(); void EnqueueDeferredTask(); - static void FreeGlobalCallBack(void* ref); static void NativeFinalizeCallBack(void* ref); +private: + static void FreeGlobalCallBack(void* ref); friend class NativeReferenceManager; }; +class ArkXRefNativeReference : public ArkNativeReference { +public: + ArkXRefNativeReference(ArkNativeEngine* engine, + napi_value value, + const ArkNativeReferenceConfig &config); + ~ArkXRefNativeReference() override; + uint32_t Unref() override; + +private: + static void FreeXRefGlobalCallBack(void* ref); +}; + #endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_REFERENCE_H */ -- Gitee