133eb0b6dSopenharmony_ci/* 233eb0b6dSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 333eb0b6dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 433eb0b6dSopenharmony_ci * you may not use this file except in compliance with the License. 533eb0b6dSopenharmony_ci * You may obtain a copy of the License at 633eb0b6dSopenharmony_ci * 733eb0b6dSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 833eb0b6dSopenharmony_ci * 933eb0b6dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1033eb0b6dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1133eb0b6dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1233eb0b6dSopenharmony_ci * See the License for the specific language governing permissions and 1333eb0b6dSopenharmony_ci * limitations under the License. 1433eb0b6dSopenharmony_ci */ 1533eb0b6dSopenharmony_ci 1633eb0b6dSopenharmony_ci#include <cinttypes> 1733eb0b6dSopenharmony_ci 1833eb0b6dSopenharmony_ci#include "ark_native_reference.h" 1933eb0b6dSopenharmony_ci 2033eb0b6dSopenharmony_ci#ifdef ENABLE_HITRACE 2133eb0b6dSopenharmony_ci#include "hitrace/trace.h" 2233eb0b6dSopenharmony_ci#include "hitrace_meter.h" 2333eb0b6dSopenharmony_ci#endif 2433eb0b6dSopenharmony_ci#include "native_engine/native_utils.h" 2533eb0b6dSopenharmony_ci#include "utils/log.h" 2633eb0b6dSopenharmony_ci 2733eb0b6dSopenharmony_ciArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, 2833eb0b6dSopenharmony_ci napi_value value, 2933eb0b6dSopenharmony_ci uint32_t initialRefcount, 3033eb0b6dSopenharmony_ci bool deleteSelf, 3133eb0b6dSopenharmony_ci NapiNativeFinalize napiCallback, 3233eb0b6dSopenharmony_ci void* data, 3333eb0b6dSopenharmony_ci void* hint, 3433eb0b6dSopenharmony_ci bool isAsyncCall, 3533eb0b6dSopenharmony_ci size_t nativeBindingSize) 3633eb0b6dSopenharmony_ci : engine_(engine), 3733eb0b6dSopenharmony_ci value_(engine->GetEcmaVm(), LocalValueFromJsValue(value)), 3833eb0b6dSopenharmony_ci refCount_(initialRefcount), 3933eb0b6dSopenharmony_ci deleteSelf_(deleteSelf), 4033eb0b6dSopenharmony_ci isAsyncCall_(isAsyncCall), 4133eb0b6dSopenharmony_ci napiCallback_(napiCallback), 4233eb0b6dSopenharmony_ci data_(data), 4333eb0b6dSopenharmony_ci hint_(hint), 4433eb0b6dSopenharmony_ci nativeBindingSize_(nativeBindingSize) 4533eb0b6dSopenharmony_ci{ 4633eb0b6dSopenharmony_ci ArkNativeReferenceConstructor(initialRefcount, deleteSelf); 4733eb0b6dSopenharmony_ci} 4833eb0b6dSopenharmony_ci 4933eb0b6dSopenharmony_ciArkNativeReference::ArkNativeReference(ArkNativeEngine* engine, 5033eb0b6dSopenharmony_ci Local<JSValueRef> value, 5133eb0b6dSopenharmony_ci uint32_t initialRefcount, 5233eb0b6dSopenharmony_ci bool deleteSelf, 5333eb0b6dSopenharmony_ci NapiNativeFinalize napiCallback, 5433eb0b6dSopenharmony_ci void* data, 5533eb0b6dSopenharmony_ci void* hint, 5633eb0b6dSopenharmony_ci bool isAsyncCall, 5733eb0b6dSopenharmony_ci size_t nativeBindingSize) 5833eb0b6dSopenharmony_ci : engine_(engine), 5933eb0b6dSopenharmony_ci value_(engine->GetEcmaVm(), value), 6033eb0b6dSopenharmony_ci refCount_(initialRefcount), 6133eb0b6dSopenharmony_ci deleteSelf_(deleteSelf), 6233eb0b6dSopenharmony_ci isAsyncCall_(isAsyncCall), 6333eb0b6dSopenharmony_ci napiCallback_(napiCallback), 6433eb0b6dSopenharmony_ci data_(data), 6533eb0b6dSopenharmony_ci hint_(hint), 6633eb0b6dSopenharmony_ci nativeBindingSize_(nativeBindingSize) 6733eb0b6dSopenharmony_ci{ 6833eb0b6dSopenharmony_ci ArkNativeReferenceConstructor(initialRefcount, deleteSelf); 6933eb0b6dSopenharmony_ci} 7033eb0b6dSopenharmony_ci 7133eb0b6dSopenharmony_ciArkNativeReference::~ArkNativeReference() 7233eb0b6dSopenharmony_ci{ 7333eb0b6dSopenharmony_ci if (deleteSelf_ && engine_->GetReferenceManager()) { 7433eb0b6dSopenharmony_ci engine_->GetReferenceManager()->ReleaseHandler(this); 7533eb0b6dSopenharmony_ci prev_ = nullptr; 7633eb0b6dSopenharmony_ci next_ = nullptr; 7733eb0b6dSopenharmony_ci } 7833eb0b6dSopenharmony_ci if (value_.IsEmpty()) { 7933eb0b6dSopenharmony_ci return; 8033eb0b6dSopenharmony_ci } 8133eb0b6dSopenharmony_ci hasDelete_ = true; 8233eb0b6dSopenharmony_ci value_.FreeGlobalHandleAddr(); 8333eb0b6dSopenharmony_ci FinalizeCallback(FinalizerState::DESTRUCTION); 8433eb0b6dSopenharmony_ci} 8533eb0b6dSopenharmony_ci 8633eb0b6dSopenharmony_ciuint32_t ArkNativeReference::Ref() 8733eb0b6dSopenharmony_ci{ 8833eb0b6dSopenharmony_ci ++refCount_; 8933eb0b6dSopenharmony_ci if (refCount_ == 1) { 9033eb0b6dSopenharmony_ci value_.ClearWeak(); 9133eb0b6dSopenharmony_ci } 9233eb0b6dSopenharmony_ci return refCount_; 9333eb0b6dSopenharmony_ci} 9433eb0b6dSopenharmony_ci 9533eb0b6dSopenharmony_ciuint32_t ArkNativeReference::Unref() 9633eb0b6dSopenharmony_ci{ 9733eb0b6dSopenharmony_ci if (refCount_ == 0) { 9833eb0b6dSopenharmony_ci return refCount_; 9933eb0b6dSopenharmony_ci } 10033eb0b6dSopenharmony_ci --refCount_; 10133eb0b6dSopenharmony_ci if (value_.IsEmpty()) { 10233eb0b6dSopenharmony_ci return refCount_; 10333eb0b6dSopenharmony_ci } 10433eb0b6dSopenharmony_ci if (refCount_ == 0) { 10533eb0b6dSopenharmony_ci value_.SetWeakCallback(reinterpret_cast<void*>(this), FreeGlobalCallBack, NativeFinalizeCallBack); 10633eb0b6dSopenharmony_ci } 10733eb0b6dSopenharmony_ci return refCount_; 10833eb0b6dSopenharmony_ci} 10933eb0b6dSopenharmony_ci 11033eb0b6dSopenharmony_cinapi_value ArkNativeReference::Get(NativeEngine* engine) 11133eb0b6dSopenharmony_ci{ 11233eb0b6dSopenharmony_ci if (value_.IsEmpty()) { 11333eb0b6dSopenharmony_ci return nullptr; 11433eb0b6dSopenharmony_ci } 11533eb0b6dSopenharmony_ci if (engine != engine_) { 11633eb0b6dSopenharmony_ci LOG_IF_SPECIAL(UNLIKELY(engine->IsCrossThreadCheckEnabled()), 11733eb0b6dSopenharmony_ci "param env is not equal to its owner"); 11833eb0b6dSopenharmony_ci } else if (engineId_ != engine->GetId()) { 11933eb0b6dSopenharmony_ci LOG_IF_SPECIAL(UNLIKELY(engine->IsCrossThreadCheckEnabled()), 12033eb0b6dSopenharmony_ci "param env is not equal to its owner, " 12133eb0b6dSopenharmony_ci "current env id: %{public}" PRIu64 ", owner id: %{public}" PRIu64, 12233eb0b6dSopenharmony_ci engineId_, engine_->GetId()); 12333eb0b6dSopenharmony_ci } 12433eb0b6dSopenharmony_ci Local<JSValueRef> value = value_.ToLocal(engine->GetEcmaVm()); 12533eb0b6dSopenharmony_ci return JsValueFromLocalValue(value); 12633eb0b6dSopenharmony_ci} 12733eb0b6dSopenharmony_ci 12833eb0b6dSopenharmony_cinapi_value ArkNativeReference::Get() 12933eb0b6dSopenharmony_ci{ 13033eb0b6dSopenharmony_ci if (value_.IsEmpty()) { 13133eb0b6dSopenharmony_ci return nullptr; 13233eb0b6dSopenharmony_ci } 13333eb0b6dSopenharmony_ci if (engineId_ != engine_->GetId()) { 13433eb0b6dSopenharmony_ci LOG_IF_SPECIAL(UNLIKELY(engine_->IsCrossThreadCheckEnabled()), 13533eb0b6dSopenharmony_ci "owner env has been destroyed, " 13633eb0b6dSopenharmony_ci "current env id: %{public}" PRIu64 ", owner id: %{public}" PRIu64, 13733eb0b6dSopenharmony_ci engineId_, engine_->GetId()); 13833eb0b6dSopenharmony_ci } 13933eb0b6dSopenharmony_ci Local<JSValueRef> value = value_.ToLocal(engine_->GetEcmaVm()); 14033eb0b6dSopenharmony_ci return JsValueFromLocalValue(value); 14133eb0b6dSopenharmony_ci} 14233eb0b6dSopenharmony_ci 14333eb0b6dSopenharmony_ciArkNativeReference::operator napi_value() 14433eb0b6dSopenharmony_ci{ 14533eb0b6dSopenharmony_ci return Get(); 14633eb0b6dSopenharmony_ci} 14733eb0b6dSopenharmony_ci 14833eb0b6dSopenharmony_civoid* ArkNativeReference::GetData() 14933eb0b6dSopenharmony_ci{ 15033eb0b6dSopenharmony_ci return data_; 15133eb0b6dSopenharmony_ci} 15233eb0b6dSopenharmony_ci 15333eb0b6dSopenharmony_civoid ArkNativeReference::FinalizeCallback(FinalizerState state) 15433eb0b6dSopenharmony_ci{ 15533eb0b6dSopenharmony_ci if (napiCallback_ != nullptr && !engine_->IsInDestructor()) { 15633eb0b6dSopenharmony_ci if (state == FinalizerState::COLLECTION) { 15733eb0b6dSopenharmony_ci std::tuple<NativeEngine*, void*, void*> tuple = std::make_tuple(engine_, data_, hint_); 15833eb0b6dSopenharmony_ci RefFinalizer finalizer = std::make_pair(napiCallback_, tuple); 15933eb0b6dSopenharmony_ci if (isAsyncCall_) { 16033eb0b6dSopenharmony_ci engine_->GetPendingAsyncFinalizers().emplace_back(finalizer); 16133eb0b6dSopenharmony_ci } else { 16233eb0b6dSopenharmony_ci engine_->GetArkFinalizersPack().AddFinalizer(finalizer, nativeBindingSize_); 16333eb0b6dSopenharmony_ci } 16433eb0b6dSopenharmony_ci } else { 16533eb0b6dSopenharmony_ci napiCallback_(reinterpret_cast<napi_env>(engine_), data_, hint_); 16633eb0b6dSopenharmony_ci } 16733eb0b6dSopenharmony_ci } 16833eb0b6dSopenharmony_ci napiCallback_ = nullptr; 16933eb0b6dSopenharmony_ci data_ = nullptr; 17033eb0b6dSopenharmony_ci hint_ = nullptr; 17133eb0b6dSopenharmony_ci finalRun_ = true; 17233eb0b6dSopenharmony_ci 17333eb0b6dSopenharmony_ci if (deleteSelf_ && !hasDelete_) { 17433eb0b6dSopenharmony_ci delete this; 17533eb0b6dSopenharmony_ci } 17633eb0b6dSopenharmony_ci} 17733eb0b6dSopenharmony_ci 17833eb0b6dSopenharmony_civoid ArkNativeReference::FreeGlobalCallBack(void* ref) 17933eb0b6dSopenharmony_ci{ 18033eb0b6dSopenharmony_ci auto that = reinterpret_cast<ArkNativeReference*>(ref); 18133eb0b6dSopenharmony_ci that->value_.FreeGlobalHandleAddr(); 18233eb0b6dSopenharmony_ci} 18333eb0b6dSopenharmony_ci 18433eb0b6dSopenharmony_civoid ArkNativeReference::NativeFinalizeCallBack(void* ref) 18533eb0b6dSopenharmony_ci{ 18633eb0b6dSopenharmony_ci auto that = reinterpret_cast<ArkNativeReference*>(ref); 18733eb0b6dSopenharmony_ci that->FinalizeCallback(FinalizerState::COLLECTION); 18833eb0b6dSopenharmony_ci} 18933eb0b6dSopenharmony_ci 19033eb0b6dSopenharmony_civoid ArkNativeReference::SetDeleteSelf() 19133eb0b6dSopenharmony_ci{ 19233eb0b6dSopenharmony_ci deleteSelf_ = true; 19333eb0b6dSopenharmony_ci} 19433eb0b6dSopenharmony_ci 19533eb0b6dSopenharmony_cibool ArkNativeReference::GetDeleteSelf() const 19633eb0b6dSopenharmony_ci{ 19733eb0b6dSopenharmony_ci return deleteSelf_; 19833eb0b6dSopenharmony_ci} 19933eb0b6dSopenharmony_ci 20033eb0b6dSopenharmony_ciuint32_t ArkNativeReference::GetRefCount() 20133eb0b6dSopenharmony_ci{ 20233eb0b6dSopenharmony_ci return refCount_; 20333eb0b6dSopenharmony_ci} 20433eb0b6dSopenharmony_ci 20533eb0b6dSopenharmony_cibool ArkNativeReference::GetFinalRun() 20633eb0b6dSopenharmony_ci{ 20733eb0b6dSopenharmony_ci return finalRun_; 20833eb0b6dSopenharmony_ci} 20933eb0b6dSopenharmony_ci 21033eb0b6dSopenharmony_cinapi_value ArkNativeReference::GetNapiValue() 21133eb0b6dSopenharmony_ci{ 21233eb0b6dSopenharmony_ci return Get(); 21333eb0b6dSopenharmony_ci} 21433eb0b6dSopenharmony_ci 21533eb0b6dSopenharmony_civoid ArkNativeReference::ResetFinalizer() 21633eb0b6dSopenharmony_ci{ 21733eb0b6dSopenharmony_ci napiCallback_ = nullptr; 21833eb0b6dSopenharmony_ci data_ = nullptr; 21933eb0b6dSopenharmony_ci hint_ = nullptr; 22033eb0b6dSopenharmony_ci}