xref: /aosp_15_r20/external/fbjni/cxx/fbjni/detail/ReferenceAllocators-inl.h (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <atomic>
20 #include <cassert>
21 #include <new>
22 
23 #include <fbjni/detail/FbjniApi.h>
24 #include "Environment.h"
25 
26 namespace facebook {
27 namespace jni {
28 
29 /// @cond INTERNAL
30 namespace internal {
31 
32 // Statistics mostly provided for test (only updated if FBJNI_DEBUG_REFS is
33 // defined)
34 struct ReferenceStats {
35   std::atomic_uint locals_created, globals_created, weaks_created,
36       locals_deleted, globals_deleted, weaks_deleted;
37 
38   void reset() noexcept;
39 };
40 
41 extern FBJNI_API ReferenceStats g_reference_stats;
42 } // namespace internal
43 /// @endcond
44 
45 // LocalReferenceAllocator
46 // /////////////////////////////////////////////////////////////////////////
47 
newReference(jobject original)48 inline jobject LocalReferenceAllocator::newReference(jobject original) const {
49   internal::dbglog("Local new: %p", original);
50 #ifdef FBJNI_DEBUG_REFS
51   ++internal::g_reference_stats.locals_created;
52 #endif
53   auto ref = Environment::current()->NewLocalRef(original);
54   FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
55   return ref;
56 }
57 
deleteReference(jobject reference)58 inline void LocalReferenceAllocator::deleteReference(
59     jobject reference) const noexcept {
60   internal::dbglog("Local release: %p", reference);
61 
62   if (reference) {
63 #ifdef FBJNI_DEBUG_REFS
64     ++internal::g_reference_stats.locals_deleted;
65 #endif
66     assert(verifyReference(reference));
67     Environment::current()->DeleteLocalRef(reference);
68   }
69 }
70 
verifyReference(jobject reference)71 inline bool LocalReferenceAllocator::verifyReference(
72     jobject reference) const noexcept {
73   return isObjectRefType(reference, JNILocalRefType);
74 }
75 
76 // GlobalReferenceAllocator
77 // ////////////////////////////////////////////////////////////////////////
78 
newReference(jobject original)79 inline jobject GlobalReferenceAllocator::newReference(jobject original) const {
80   internal::dbglog("Global new: %p", original);
81 #ifdef FBJNI_DEBUG_REFS
82   ++internal::g_reference_stats.globals_created;
83 #endif
84   auto ref = Environment::current()->NewGlobalRef(original);
85   FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
86   return ref;
87 }
88 
deleteReference(jobject reference)89 inline void GlobalReferenceAllocator::deleteReference(
90     jobject reference) const noexcept {
91   internal::dbglog("Global release: %p", reference);
92 
93   if (reference) {
94 #ifdef FBJNI_DEBUG_REFS
95     ++internal::g_reference_stats.globals_deleted;
96 #endif
97     assert(verifyReference(reference));
98     Environment::current()->DeleteGlobalRef(reference);
99   }
100 }
101 
verifyReference(jobject reference)102 inline bool GlobalReferenceAllocator::verifyReference(
103     jobject reference) const noexcept {
104   return isObjectRefType(reference, JNIGlobalRefType);
105 }
106 
107 // WeakGlobalReferenceAllocator
108 // ////////////////////////////////////////////////////////////////////
109 
newReference(jobject original)110 inline jobject WeakGlobalReferenceAllocator::newReference(
111     jobject original) const {
112   internal::dbglog("Weak global new: %p", original);
113 #ifdef FBJNI_DEBUG_REFS
114   ++internal::g_reference_stats.weaks_created;
115 #endif
116   auto ref = Environment::current()->NewWeakGlobalRef(original);
117   FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
118   return ref;
119 }
120 
deleteReference(jobject reference)121 inline void WeakGlobalReferenceAllocator::deleteReference(
122     jobject reference) const noexcept {
123   internal::dbglog("Weak Global release: %p", reference);
124 
125   if (reference) {
126 #ifdef FBJNI_DEBUG_REFS
127     ++internal::g_reference_stats.weaks_deleted;
128 #endif
129     assert(verifyReference(reference));
130     Environment::current()->DeleteWeakGlobalRef(reference);
131   }
132 }
133 
verifyReference(jobject reference)134 inline bool WeakGlobalReferenceAllocator::verifyReference(
135     jobject reference) const noexcept {
136   return isObjectRefType(reference, JNIWeakGlobalRefType);
137 }
138 
139 } // namespace jni
140 } // namespace facebook
141