1 /*
2 * Copyright (c) 2021 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 #include <cinttypes>
17
18 #include "ark_native_reference.h"
19
20 #ifdef ENABLE_HITRACE
21 #include "hitrace/trace.h"
22 #include "hitrace_meter.h"
23 #endif
24 #include "native_engine/native_utils.h"
25 #include "utils/log.h"
26
ArkNativeReference(ArkNativeEngine * engine,napi_value value,uint32_t initialRefcount,bool deleteSelf,NapiNativeFinalize napiCallback,void * data,void * hint,bool isAsyncCall,size_t nativeBindingSize)27 ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine,
28 napi_value value,
29 uint32_t initialRefcount,
30 bool deleteSelf,
31 NapiNativeFinalize napiCallback,
32 void* data,
33 void* hint,
34 bool isAsyncCall,
35 size_t nativeBindingSize)
36 : engine_(engine),
37 value_(engine->GetEcmaVm(), LocalValueFromJsValue(value)),
38 refCount_(initialRefcount),
39 deleteSelf_(deleteSelf),
40 isAsyncCall_(isAsyncCall),
41 napiCallback_(napiCallback),
42 data_(data),
43 hint_(hint),
44 nativeBindingSize_(nativeBindingSize)
45 {
46 ArkNativeReferenceConstructor(initialRefcount, deleteSelf);
47 }
48
ArkNativeReference(ArkNativeEngine * engine,Local<JSValueRef> value,uint32_t initialRefcount,bool deleteSelf,NapiNativeFinalize napiCallback,void * data,void * hint,bool isAsyncCall,size_t nativeBindingSize)49 ArkNativeReference::ArkNativeReference(ArkNativeEngine* engine,
50 Local<JSValueRef> value,
51 uint32_t initialRefcount,
52 bool deleteSelf,
53 NapiNativeFinalize napiCallback,
54 void* data,
55 void* hint,
56 bool isAsyncCall,
57 size_t nativeBindingSize)
58 : engine_(engine),
59 value_(engine->GetEcmaVm(), value),
60 refCount_(initialRefcount),
61 deleteSelf_(deleteSelf),
62 isAsyncCall_(isAsyncCall),
63 napiCallback_(napiCallback),
64 data_(data),
65 hint_(hint),
66 nativeBindingSize_(nativeBindingSize)
67 {
68 ArkNativeReferenceConstructor(initialRefcount, deleteSelf);
69 }
70
~ArkNativeReference()71 ArkNativeReference::~ArkNativeReference()
72 {
73 if (deleteSelf_ && engine_->GetReferenceManager()) {
74 engine_->GetReferenceManager()->ReleaseHandler(this);
75 prev_ = nullptr;
76 next_ = nullptr;
77 }
78 if (value_.IsEmpty()) {
79 return;
80 }
81 hasDelete_ = true;
82 value_.FreeGlobalHandleAddr();
83 FinalizeCallback(FinalizerState::DESTRUCTION);
84 }
85
Ref()86 uint32_t ArkNativeReference::Ref()
87 {
88 ++refCount_;
89 if (refCount_ == 1) {
90 value_.ClearWeak();
91 }
92 return refCount_;
93 }
94
Unref()95 uint32_t ArkNativeReference::Unref()
96 {
97 if (refCount_ == 0) {
98 return refCount_;
99 }
100 --refCount_;
101 if (value_.IsEmpty()) {
102 return refCount_;
103 }
104 if (refCount_ == 0) {
105 value_.SetWeakCallback(reinterpret_cast<void*>(this), FreeGlobalCallBack, NativeFinalizeCallBack);
106 }
107 return refCount_;
108 }
109
Get(NativeEngine * engine)110 napi_value ArkNativeReference::Get(NativeEngine* engine)
111 {
112 if (value_.IsEmpty()) {
113 return nullptr;
114 }
115 if (engine != engine_) {
116 LOG_IF_SPECIAL(UNLIKELY(engine->IsCrossThreadCheckEnabled()),
117 "param env is not equal to its owner");
118 } else if (engineId_ != engine->GetId()) {
119 LOG_IF_SPECIAL(UNLIKELY(engine->IsCrossThreadCheckEnabled()),
120 "param env is not equal to its owner, "
121 "current env id: %{public}" PRIu64 ", owner id: %{public}" PRIu64,
122 engineId_, engine_->GetId());
123 }
124 Local<JSValueRef> value = value_.ToLocal(engine->GetEcmaVm());
125 return JsValueFromLocalValue(value);
126 }
127
Get()128 napi_value ArkNativeReference::Get()
129 {
130 if (value_.IsEmpty()) {
131 return nullptr;
132 }
133 if (engineId_ != engine_->GetId()) {
134 LOG_IF_SPECIAL(UNLIKELY(engine_->IsCrossThreadCheckEnabled()),
135 "owner env has been destroyed, "
136 "current env id: %{public}" PRIu64 ", owner id: %{public}" PRIu64,
137 engineId_, engine_->GetId());
138 }
139 Local<JSValueRef> value = value_.ToLocal(engine_->GetEcmaVm());
140 return JsValueFromLocalValue(value);
141 }
142
143 ArkNativeReference::operator napi_value()
144 {
145 return Get();
146 }
147
GetData()148 void* ArkNativeReference::GetData()
149 {
150 return data_;
151 }
152
FinalizeCallback(FinalizerState state)153 void ArkNativeReference::FinalizeCallback(FinalizerState state)
154 {
155 if (napiCallback_ != nullptr && !engine_->IsInDestructor()) {
156 if (state == FinalizerState::COLLECTION) {
157 std::tuple<NativeEngine*, void*, void*> tuple = std::make_tuple(engine_, data_, hint_);
158 RefFinalizer finalizer = std::make_pair(napiCallback_, tuple);
159 if (isAsyncCall_) {
160 engine_->GetPendingAsyncFinalizers().emplace_back(finalizer);
161 } else {
162 engine_->GetArkFinalizersPack().AddFinalizer(finalizer, nativeBindingSize_);
163 }
164 } else {
165 napiCallback_(reinterpret_cast<napi_env>(engine_), data_, hint_);
166 }
167 }
168 napiCallback_ = nullptr;
169 data_ = nullptr;
170 hint_ = nullptr;
171 finalRun_ = true;
172
173 if (deleteSelf_ && !hasDelete_) {
174 delete this;
175 }
176 }
177
FreeGlobalCallBack(void * ref)178 void ArkNativeReference::FreeGlobalCallBack(void* ref)
179 {
180 auto that = reinterpret_cast<ArkNativeReference*>(ref);
181 that->value_.FreeGlobalHandleAddr();
182 }
183
NativeFinalizeCallBack(void * ref)184 void ArkNativeReference::NativeFinalizeCallBack(void* ref)
185 {
186 auto that = reinterpret_cast<ArkNativeReference*>(ref);
187 that->FinalizeCallback(FinalizerState::COLLECTION);
188 }
189
SetDeleteSelf()190 void ArkNativeReference::SetDeleteSelf()
191 {
192 deleteSelf_ = true;
193 }
194
GetDeleteSelf() const195 bool ArkNativeReference::GetDeleteSelf() const
196 {
197 return deleteSelf_;
198 }
199
GetRefCount()200 uint32_t ArkNativeReference::GetRefCount()
201 {
202 return refCount_;
203 }
204
GetFinalRun()205 bool ArkNativeReference::GetFinalRun()
206 {
207 return finalRun_;
208 }
209
GetNapiValue()210 napi_value ArkNativeReference::GetNapiValue()
211 {
212 return Get();
213 }
214
ResetFinalizer()215 void ArkNativeReference::ResetFinalizer()
216 {
217 napiCallback_ = nullptr;
218 data_ = nullptr;
219 hint_ = nullptr;
220 }