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}