1use crate::pyport::Py_ssize_t;
2use crate::PyObject;
3#[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
4use std::os::raw::c_char;
5#[cfg(Py_3_12)]
6use std::os::raw::c_int;
7#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]
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)]
18pub const _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))]
59pub const _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = c_uint::MAX as Py_ssize_t;
60
61#[cfg(Py_GIL_DISABLED)]
62pub const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;
63
64#[cfg(Py_GIL_DISABLED)]
65pub const _Py_REF_SHARED_SHIFT: isize = 2;
66#[inline]
76pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
77 #[cfg(Py_GIL_DISABLED)]
78 {
79 let local = (*ob).ob_ref_local.load(Relaxed);
80 if local == _Py_IMMORTAL_REFCNT_LOCAL {
81 #[cfg(not(Py_3_14))]
82 return _Py_IMMORTAL_REFCNT;
83 #[cfg(Py_3_14)]
84 return _Py_IMMORTAL_INITIAL_REFCNT;
85 }
86 let shared = (*ob).ob_ref_shared.load(Relaxed);
87 local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)
88 }
89
90 #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]
91 {
92 (*ob).ob_refcnt.ob_refcnt
93 }
94
95 #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]
96 {
97 (*ob).ob_refcnt
98 }
99
100 #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]
101 {
102 _Py_REFCNT(ob)
103 }
104}
105
106#[cfg(Py_3_12)]
107#[inline(always)]
108unsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {
109 #[cfg(all(target_pointer_width = "64", not(Py_GIL_DISABLED)))]
110 {
111 (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int
112 }
113
114 #[cfg(all(target_pointer_width = "32", not(Py_GIL_DISABLED)))]
115 {
116 #[cfg(not(Py_3_14))]
117 {
118 ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int
119 }
120
121 #[cfg(Py_3_14)]
122 {
123 ((*op).ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT) as c_int
124 }
125 }
126
127 #[cfg(Py_GIL_DISABLED)]
128 {
129 ((*op).ob_ref_local.load(Relaxed) == _Py_IMMORTAL_REFCNT_LOCAL) as c_int
130 }
131}
132
133extern "C" {
138 #[cfg(all(py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
139 fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);
140 #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
141 fn _Py_INCREF_IncRefTotal();
142 #[cfg(all(Py_3_12, py_sys_config = "Py_REF_DEBUG", not(Py_LIMITED_API)))]
143 fn _Py_DECREF_DecRefTotal();
144
145 #[cfg_attr(PyPy, link_name = "_PyPy_Dealloc")]
146 fn _Py_Dealloc(arg1: *mut PyObject);
147
148 #[cfg_attr(PyPy, link_name = "PyPy_IncRef")]
149 #[cfg_attr(GraalPy, link_name = "_Py_IncRef")]
150 pub fn Py_IncRef(o: *mut PyObject);
151 #[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
152 #[cfg_attr(GraalPy, link_name = "_Py_DecRef")]
153 pub fn Py_DecRef(o: *mut PyObject);
154
155 #[cfg(all(Py_3_10, not(PyPy)))]
156 fn _Py_IncRef(o: *mut PyObject);
157 #[cfg(all(Py_3_10, not(PyPy)))]
158 fn _Py_DecRef(o: *mut PyObject);
159
160 #[cfg(GraalPy)]
161 fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;
162
163 #[cfg(GraalPy)]
164 fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject;
165
166 #[cfg(GraalPy)]
167 fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t;
168}
169
170#[inline(always)]
171pub unsafe fn Py_INCREF(op: *mut PyObject) {
172 #[cfg(any(
175 Py_GIL_DISABLED,
176 Py_LIMITED_API,
177 py_sys_config = "Py_REF_DEBUG",
178 GraalPy
179 ))]
180 {
181 #[cfg(all(Py_3_10, not(PyPy)))]
183 {
184 _Py_IncRef(op);
185 }
186
187 #[cfg(any(not(Py_3_10), PyPy))]
188 {
189 Py_IncRef(op);
190 }
191 }
192
193 #[cfg(not(any(
195 Py_GIL_DISABLED,
196 Py_LIMITED_API,
197 py_sys_config = "Py_REF_DEBUG",
198 GraalPy
199 )))]
200 {
201 #[cfg(all(Py_3_14, target_pointer_width = "64"))]
202 {
203 let cur_refcnt = (*op).ob_refcnt.ob_refcnt;
204 if (cur_refcnt as i32) < 0 {
205 return;
206 }
207 (*op).ob_refcnt.ob_refcnt = cur_refcnt.wrapping_add(1);
208 }
209
210 #[cfg(all(Py_3_12, not(Py_3_14), target_pointer_width = "64"))]
211 {
212 let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];
213 let new_refcnt = cur_refcnt.wrapping_add(1);
214 if new_refcnt == 0 {
215 return;
216 }
217 (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;
218 }
219
220 #[cfg(all(Py_3_12, target_pointer_width = "32"))]
221 {
222 if _Py_IsImmortal(op) != 0 {
223 return;
224 }
225 (*op).ob_refcnt.ob_refcnt += 1
226 }
227
228 #[cfg(not(Py_3_12))]
229 {
230 (*op).ob_refcnt += 1
231 }
232
233 }
236}
237
238#[inline(always)]
243#[cfg_attr(
244 all(py_sys_config = "Py_REF_DEBUG", Py_3_12, not(Py_LIMITED_API)),
245 track_caller
246)]
247pub unsafe fn Py_DECREF(op: *mut PyObject) {
248 #[cfg(any(
252 Py_GIL_DISABLED,
253 Py_LIMITED_API,
254 all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
255 GraalPy
256 ))]
257 {
258 #[cfg(all(Py_3_10, not(PyPy)))]
260 {
261 _Py_DecRef(op);
262 }
263
264 #[cfg(any(not(Py_3_10), PyPy))]
265 {
266 Py_DecRef(op);
267 }
268 }
269
270 #[cfg(not(any(
271 Py_GIL_DISABLED,
272 Py_LIMITED_API,
273 all(py_sys_config = "Py_REF_DEBUG", not(Py_3_12)),
274 GraalPy
275 )))]
276 {
277 #[cfg(Py_3_12)]
278 if _Py_IsImmortal(op) != 0 {
279 return;
280 }
281
282 #[cfg(py_sys_config = "Py_REF_DEBUG")]
286 _Py_DECREF_DecRefTotal();
287
288 #[cfg(Py_3_12)]
289 {
290 (*op).ob_refcnt.ob_refcnt -= 1;
291
292 #[cfg(py_sys_config = "Py_REF_DEBUG")]
293 if (*op).ob_refcnt.ob_refcnt < 0 {
294 let location = std::panic::Location::caller();
295 let filename = std::ffi::CString::new(location.file()).unwrap();
296 _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);
297 }
298
299 if (*op).ob_refcnt.ob_refcnt == 0 {
300 _Py_Dealloc(op);
301 }
302 }
303
304 #[cfg(not(Py_3_12))]
305 {
306 (*op).ob_refcnt -= 1;
307
308 if (*op).ob_refcnt == 0 {
309 _Py_Dealloc(op);
310 }
311 }
312 }
313}
314
315#[inline]
316pub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {
317 let tmp = *op;
318 if !tmp.is_null() {
319 *op = ptr::null_mut();
320 Py_DECREF(tmp);
321 }
322}
323
324#[inline]
325pub unsafe fn Py_XINCREF(op: *mut PyObject) {
326 if !op.is_null() {
327 Py_INCREF(op)
328 }
329}
330
331#[inline]
332pub unsafe fn Py_XDECREF(op: *mut PyObject) {
333 if !op.is_null() {
334 Py_DECREF(op)
335 }
336}
337
338extern "C" {
339 #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
340 #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
341 pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
342 #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]
343 #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
344 pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
345}
346
347#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
351#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
352#[inline]
353pub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
354 Py_INCREF(obj);
355 obj
356}
357
358#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]
359#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
360#[inline]
361pub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
362 Py_XINCREF(obj);
363 obj
364}