diff --git a/napi.gni b/napi.gni index 2872c4dcb9dcc90328bf523a57de79b61c9ba011..4551c9b28ad277259dedde7c75f45051b261a23e 100755 --- a/napi.gni +++ b/napi.gni @@ -41,6 +41,11 @@ napi_sources = [ "utils/log.cpp", ] +# supported for hybrid +napi_sources += [ + "native_engine/impl/ark/ark_hybrid_native_reference.cpp", +] + if (is_mingw) { napi_sources += [ "utils/platform/windows/file.cpp" ] } else { diff --git a/native_engine/impl/ark/ark_hybrid_native_reference.cpp b/native_engine/impl/ark/ark_hybrid_native_reference.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e922c125c163835994d579c472d1650fca8e54e --- /dev/null +++ b/native_engine/impl/ark/ark_hybrid_native_reference.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ark_hybrid_native_reference.h" + +#include + +#include "native_engine/native_api_internal.h" +#include "native_engine/native_utils.h" + +ArkXRefNativeReference::ArkXRefNativeReference(ArkNativeEngine* engine, + napi_value value, + const ArkNativeReferenceConfig &config) + : ArkNativeReference(engine, config) +{ + value_.CreateXRefGloablReference(engine->GetEcmaVm(), LocalValueFromJsValue(value)); + ArkNativeReferenceConstructor(); +} + +ArkXRefNativeReference::~ArkXRefNativeReference() +{ + VALID_ENGINE_CHECK(engine_, engine_, engineId_); + + if (value_.IsEmpty()) { + return; + } + value_.FreeXRefGlobalHandleAddr(); +} + +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_; +} + +void ArkXRefNativeReference::ArkNativeReferenceConstructor() +{ + if (napiCallback_ != nullptr) { + // Async callback will redirect to root engine, no monitoring needed. + if (!IsAsyncCall()) { + engine_->IncreaseCallbackbleRefCounter(); + // Non-callback runtime owned napi_ref will free when env teardown. + if (ownership_ == ReferenceOwnerShip::RUNTIME && !engine_->IsMainEnvContext()) { + engine_->IncreaseRuntimeOwnedRefCounter(); + } + } + } else { + engine_->IncreaseNonCallbackRefCounter(); + } + + if (refCount_ == 0) { + value_.SetWeakCallback(reinterpret_cast(this), FreeXRefGlobalCallBack, NativeFinalizeCallBack); + } + + if (ownership_ == ReferenceOwnerShip::RUNTIME) { + NativeReferenceManager* referenceManager = engine_->GetReferenceManager(); + if (referenceManager != nullptr) { + referenceManager->CreateHandler(this); + } + } + + engineId_ = engine_->GetId(); +} + \ No newline at end of file diff --git a/native_engine/impl/ark/ark_hybrid_native_reference.h b/native_engine/impl/ark/ark_hybrid_native_reference.h new file mode 100644 index 0000000000000000000000000000000000000000..05ddd9b77af98c994697b83e13b29bd4ba7964b2 --- /dev/null +++ b/native_engine/impl/ark/ark_hybrid_native_reference.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_XREF_REFERENCE_H +#define FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_XREF_REFERENCE_H + +#include "native_engine/impl/ark/ark_native_reference.h" + +class ArkXRefNativeReference : public ArkNativeReference { +public: + ArkXRefNativeReference(ArkNativeEngine* engine, + napi_value value, + const ArkNativeReferenceConfig &config); + ~ArkXRefNativeReference() override; + uint32_t Unref() override; + +protected: + void ArkNativeReferenceConstructor() override; + +private: + static void FreeXRefGlobalCallBack(void* ref); +}; + +#endif /* FOUNDATION_ACE_NAPI_NATIVE_ENGINE_ARK_NATIVE_XREF_REFERENCE_H */ + \ No newline at end of file diff --git a/native_engine/impl/ark/ark_native_engine.cpp b/native_engine/impl/ark/ark_native_engine.cpp index da3bddf7158882da4d1a641d051c5442b164c4e6..3346185c4e6c08daadaa923577685c89c00be7cc 100644 --- a/native_engine/impl/ark/ark_native_engine.cpp +++ b/native_engine/impl/ark/ark_native_engine.cpp @@ -22,6 +22,7 @@ #include "ark_native_deferred.h" #include "ark_native_reference.h" +#include "ark_hybrid_native_reference.h" #include "ark_native_timer.h" #include "native_engine/native_utils.h" #include "native_sendable.h" @@ -1979,8 +1980,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 2a7ec59c7923617ab4656e337c79ff8d491c9954..ef60dc97c1d5bf0fdf465e4a6e4cf95cbb28eee1 100644 --- a/native_engine/impl/ark/ark_native_reference.cpp +++ b/native_engine/impl/ark/ark_native_reference.cpp @@ -42,22 +42,6 @@ ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, ArkNativeReferenceConstructor(); } -ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, - napi_value value, - ArkNativeReferenceConfig& config) - : engine_(engine), - value_(), - refCount_(config.initialRefcount), - ownership_(config.deleteSelf ? ReferenceOwnerShip::RUNTIME : ReferenceOwnerShip::USER), - isProxyReference_(config.isProxyReference), - napiCallback_(config.napiCallback), - data_(config.data) -{ - InitProperties(config.deleteSelf, false); - value_.CreateXRefGloablReference(engine->GetEcmaVm(), LocalValueFromJsValue(value)); - ArkNativeReferenceConstructor(); -} - ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, Local value, uint32_t initialRefcount, @@ -140,11 +124,7 @@ ArkNativeReference::~ArkNativeReference() return; } SetHasDelete(); - if (isProxyReference_) { - value_.FreeXRefGlobalHandleAddr(); - } else { - value_.FreeGlobalHandleAddr(); - } + value_.FreeGlobalHandleAddr(); FinalizeCallback(FinalizerState::DESTRUCTION); } @@ -292,11 +272,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) @@ -337,7 +313,7 @@ void ArkNativeReference::ResetFinalizer() hint_ = nullptr; } -inline bool ArkNativeReference::IsAsyncCall() const +bool ArkNativeReference::IsAsyncCall() const { return (properties_ & ReferencePropertiesMask::IS_ASYNC_CALL_MASK) != 0; } diff --git a/native_engine/impl/ark/ark_native_reference.h b/native_engine/impl/ark/ark_native_reference.h index 10c2728431456b4309a4df12febd429b3c80d655..3955cbf905aa3dcf37b878a60ffefe2453c51870 100644 --- a/native_engine/impl/ark/ark_native_reference.h +++ b/native_engine/impl/ark/ark_native_reference.h @@ -41,21 +41,19 @@ enum class ReferenceOwnerShip : uint8_t { struct ArkNativeReferenceConfig { uint32_t initialRefcount; - bool isProxyReference; bool deleteSelf; NapiNativeFinalize napiCallback; void* data; - ArkNativeReferenceConfig(uint32_t initialRefcount, - bool isProxyReference, - bool deleteSelf = false, - NapiNativeFinalize napiCallback = nullptr, - void* data = nullptr) + 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) + {} }; class ArkNativeReference : public NativeReference { @@ -69,9 +67,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,7 +96,19 @@ public: bool IsValidHeapObject(); #endif // PANDA_JS_ETS_HYBRID_MODE -private: +protected: + ArkNativeReference(ArkNativeEngine* engine, + const ArkNativeReferenceConfig &config) + : engine_(engine), + value_(), + refCount_(config.initialRefcount), + ownership_(config.deleteSelf ? ReferenceOwnerShip::RUNTIME : ReferenceOwnerShip::USER), + napiCallback_(config.napiCallback), + data_(config.data) + {} + + virtual void ArkNativeReferenceConstructor(); + enum ReferencePropertiesMask : uint8_t { DELETE_SELF_MASK = 1, IS_ASYNC_CALL_MASK = DELETE_SELF_MASK << 1, @@ -109,7 +116,6 @@ private: FINAL_RAN_MASK = HAS_DELETE_MASK << 1, }; - void ArkNativeReferenceConstructor(); void InitProperties(bool deleteSelf = false, bool isAsyncCall = false); ArkNativeEngine* engine_; @@ -122,7 +128,6 @@ private: // Bit-packed flags: saves memory and speeds up object creation vs. multiple bools. // std::bitset will use more memory than uint8_t number. uint8_t properties_ {0}; - bool isProxyReference_{false}; NapiNativeFinalize napiCallback_ {nullptr}; void* data_ {nullptr}; @@ -145,8 +150,9 @@ private: void IncreaseCounter(); void DecreaseCounter(); - static void FreeGlobalCallBack(void* ref); static void NativeFinalizeCallBack(void* ref); +private: + static void FreeGlobalCallBack(void* ref); friend class NativeReferenceManager; }; diff --git a/native_engine/native_node_api.cpp b/native_engine/native_node_api.cpp index f28ad3214eb2b9aec6cebea14028b5ab6ad06d4f..459d238a155ed8c9575b2b9feeaeb92fe719f08d 100644 --- a/native_engine/native_node_api.cpp +++ b/native_engine/native_node_api.cpp @@ -664,6 +664,6 @@ NAPI_EXTERN napi_status napi_setup_hybrid_environment(napi_env env) auto engine = reinterpret_cast(env); auto vm = engine->GetEcmaVm(); - panda::JSNApi::InitHybridVMEnv(vm); + panda::JSNApi::InitHybridVMEnv(const_cast(vm)); return GET_RETURN_STATUS(env); }