1use crate::pyport::Py_ssize_t;
2use crate::PyObject;
3#[cfg(py_sys_config = "Py_REF_DEBUG")]
4use std::os::raw::c_char;
5#[cfg(Py_3_12)]
6use std::os::raw::c_int;
7#[cfg(all(Py_3_14, any(not(Py_GIL_DISABLED), target_pointer_width = "32")))]
8use std::os::raw::c_long;
9#[cfg(any(Py_GIL_DISABLED, all(Py_3_12, not(Py_3_14))))]
10use std::os::raw::c_uint;
11#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
12use std::os::raw::c_ulong;
13use std::ptr;
14#[cfg(Py_GIL_DISABLED)]
15use std::sync::atomic::Ordering::Relaxed;
16
17#[cfg(Py_3_14)]
18const _Py_STATICALLY_ALLOCATED_FLAG: c_int = 1 << 7;
19
20#[cfg(all(Py_3_12, not(Py_3_14)))]
21const _Py_IMMORTAL_REFCNT: Py_ssize_t = {
22 if cfg!(target_pointer_width = "64") {
23 c_uint::MAX as Py_ssize_t
24 } else {
25 (c_uint::MAX >> 2) as Py_ssize_t
27 }
28};
29
30#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
33const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {
34 if cfg!(target_pointer_width = "64") {
35 ((3 as c_ulong) << (30 as c_ulong)) as Py_ssize_t
36 } else {
37 ((5 as c_long) << (28 as c_long)) as Py_ssize_t
38 }
39};
40
41#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
42const _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {
43 if cfg!(target_pointer_width = "64") {
44 _Py_IMMORTAL_INITIAL_REFCNT
45 | ((_Py_STATICALLY_ALLOCATED_FLAG as Py_ssize_t) << (32 as Py_ssize_t))
46 } else {
47 ((7 as c_long) << (28 as c_long)) as Py_ssize_t
48 }
49};
50
51#[cfg(all(Py_3_14, target_pointer_width = "32"))]
52const _Py_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t = ((1 as c_long) << (30 as c_long)) as Py_ssize_t;
53
54#[cfg(all(Py_3_14, target_pointer_width = "32"))]
55const _Py_STATIC_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t =
56 ((6 as c_long) << (28 as c_long)) as Py_ssize_t;
57
58#[cfg(all(Py_3_14, Py_GIL_DISABLED))]
59const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = c_uint::MAX as Py_ssize_t;
60
61#[cfg(Py_GIL_DISABLED)]
62pub(crate) const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
63
64#[cfg(Py_GIL_DISABLED)]
65const _Py_REF_SHARED_SHIFT: isize = 2;
66extern "C" {
76 #[cfg(all(Py_3_14, Py_LIMITED_API))]
77 pub fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t;
78}
79
80#[cfg(not(all(Py_3_14, Py_LIMITED_API)))]
81#[inline]
82pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
83 #[cfg(Py_GIL_DISABLED)]
84 {
85 let local = (*ob).ob_ref_local.load(Relaxed);
86 if local == _Py_IMMORTAL_REFCNT_LOCAL {
87 #[cfg(not(Py_3_14))]
88 return _Py_IMMORTAL_REFCNT;
89 #[cfg(Py_3_14)]
90 return _Py_IMMORTAL_INITIAL_REFCNT;
91 }
92 let shared = (*ob).ob_ref_shared.load(Relaxed);
93 local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
94 }
95
96 #[cfg(all(Py_LIMITED_API, Py_3_14))]
97 {
98 Py_REFCNT(ob)
99 }
100
101 #[cfg(all(not(Py_GIL_DISABLED), not(all(Py_LIMITED_API, Py_3_14)), Py_3_12))]
102 {
103 (*ob).ob_refcnt.ob_refcnt
104 }
105
106 #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]
107 {
108 (*ob).ob_refcnt
109 }
110
111 #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]
112 {
113 _Py_REFCNT(ob)
114 }
115}
116
117#[cfg(Py_3_12)]
118#[inline(always)]
119unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
120 #[cfg(all(target_pointer_width = "64", not(Py_GIL_DISABLED)))]
121 {
122 (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
123 }
124
125 #[cfg(all(target_pointer_width = "32", not(Py_GIL_DISABLED)))]
126 {
127 #[cfg(not(Py_3_14))]
128 {
129 ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
130 }
131
132 #[cfg(Py_3_14)]
133 {
134 ((*op).ob_refcnt.ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT) as c_int
135 }
136 }
137
138 #[cfg(Py_GIL_DISABLED)]
139 {
140 ((*op).ob_ref_local.load(Relaxed) == _Py_IMMORTAL_REFCNT_LOCAL) as c_int
141 }
142}
143
144extern "C" {
149 #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
150 fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
151 #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
152 fn _Py_INCREF_IncRefTotal();
153 #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
154 fn _Py_DECREF_DecRefTotal();
155
156 #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
157 fn _Py_Dealloc(arg1: *mut PyObject);
158
159 #[cfg_attr(PyPy, link_name = "PyPy_IncRef")]
160 #[cfg_attr(GraalPy, link_name = "_Py_IncRef")]
161 pub fn Py_IncRef(o: *mut PyObject);
162 #[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
163 #[cfg_attr(GraalPy, link_name = "_Py_DecRef")]
164 pub fn Py_DecRef(o: *mut PyObject);
165
166 #[cfg(all(Py_3_10, not(PyPy)))]
167 fn _Py_IncRef(o: *mut PyObject);
168 #[cfg(all(Py_3_10, not(PyPy)))]
169 fn _Py_DecRef(o: *mut PyObject);
170
171 #[cfg(GraalPy)]
172 fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;
173}
174
175#[inline(always)]
176pub unsafe fn Py_INCREF(op: *mut PyObject) {
177 #[cfg(any(
180 Py_GIL_DISABLED,
181 Py_LIMITED_API,
182 py_sys_config = "Py_REF_DEBUG",
183 GraalPy
184 ))]
185 {
186 #[cfg(all(Py_3_10, not(PyPy)))]
188 {
189 _Py_IncRef(op);
190 }
191
192 #[cfg(any(not(Py_3_10), PyPy))]
193 {
194 Py_IncRef(op);
195 }
196 }
197
198 #[cfg(not(any(
200 Py_GIL_DISABLED,
201 Py_LIMITED_API,
202 py_sys_config = "Py_REF_DEBUG",
203 GraalPy
204 )))]
205 {
206 #[cfg(all(Py_3_14, target_pointer_width = "64"))]
207 {
208 let cur_refcnt = (*op).ob_refcnt.ob_refcnt;
209 if (cur_refcnt as i32) < 0 {
210 return;
211 }
212 (*op).ob_refcnt.ob_refcnt = cur_refcnt.wrapping_add(1);
213 }
214
215 #[cfg(all(Py_3_12, not(Py_3_14), target_pointer_width = "64"))]
216 {
217 let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
218 let new_refcnt = cur_refcnt.wrapping_add(1);
219 if new_refcnt == 0 {
220 return;
221 }
222 (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
223 }
224
225 #[cfg(all(Py_3_12, target_pointer_width = "32"))]
226 {
227 if _Py_IsImmortal(op) != 0 {
228 return;
229 }
230 (*op).ob_refcnt.ob_refcnt += 1
231 }
232
233 #[cfg(not(Py_3_12))]
234 {
235 (*op).ob_refcnt += 1
236 }
237
238 }
241}
242
243#[inline(always)]
248#[cfg_attr(
249 all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
250 track_caller
251)]
252pub unsafe fn Py_DECREF(op: *mut PyObject) {
253 #[cfg(any(
257 Py_GIL_DISABLED,
258 Py_LIMITED_API,
259 all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
260 GraalPy
261 ))]
262 {
263 #[cfg(all(Py_3_10, not(PyPy)))]
265 {
266 _Py_DecRef(op);
267 }
268
269 #[cfg(any(not(Py_3_10), PyPy))]
270 {
271 Py_DecRef(op);
272 }
273 }
274
275 #[cfg(not(any(
276 Py_GIL_DISABLED,
277 Py_LIMITED_API,
278 all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
279 GraalPy
280 )))]
281 {
282 #[cfg(Py_3_12)]
283 if _Py_IsImmortal(op) != 0 {
284 return;
285 }
286
287 #[cfg(py_sys_config = "Py_REF_DEBUG")]
291 _Py_DECREF_DecRefTotal();
292
293 #[cfg(Py_3_12)]
294 {
295 (*op).ob_refcnt.ob_refcnt -= 1;
296
297 #[cfg(py_sys_config = "Py_REF_DEBUG")]
298 if (*op).ob_refcnt.ob_refcnt < 0 {
299 let location = std::panic::Location::caller();
300 let filename = std::ffi::CString::new(location.file()).unwrap();
301 _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
302 }
303
304 if (*op).ob_refcnt.ob_refcnt == 0 {
305 _Py_Dealloc(op);
306 }
307 }
308
309 #[cfg(not(Py_3_12))]
310 {
311 (*op).ob_refcnt -= 1;
312
313 if (*op).ob_refcnt == 0 {
314 _Py_Dealloc(op);
315 }
316 }
317 }
318}
319
320#[inline]
321pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
322 let tmp = *op;
323 if !tmp.is_null() {
324 *op = ptr::null_mut();
325 Py_DECREF(tmp);
326 }
327}
328
329#[inline]
330pub unsafe fn Py_XINCREF(op: *mut PyObject) {
331 if !op.is_null() {
332 Py_INCREF(op)
333 }
334}
335
336#[inline]
337pub unsafe fn Py_XDECREF(op: *mut PyObject) {
338 if !op.is_null() {
339 Py_DECREF(op)
340 }
341}
342
343extern "C" {
344 #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
345 #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
346 pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
347 #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
348 #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
349 pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
350}
351
352#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
356#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
357#[inline]
358pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
359 Py_INCREF(obj);
360 obj
361}
362
363#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
364#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
365#[inline]
366pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
367 Py_XINCREF(obj);
368 obj
369}