@@ -19,6 +19,9 @@ immortal. The latter should be the only instances that require
1919cleanup during runtime finalization.
2020*/
2121
22+ /* Leave the low bits for refcount overflow for old stable ABI code */
23+ #define _Py_STATICALLY_ALLOCATED_FLAG (1 << 7)
24+
2225#if SIZEOF_VOID_P > 4
2326/*
2427In 64+ bit systems, any object whose 32 bit reference count is >= 2**31
@@ -39,7 +42,8 @@ beyond the refcount limit. Immortality checks for reference count decreases will
3942be done by checking the bit sign flag in the lower 32 bits.
4043
4144*/
42- #define _Py_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(3UL << 30))
45+ #define _Py_IMMORTAL_INITIAL_REFCNT (3UL << 30)
46+ #define _Py_STATIC_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(_Py_IMMORTAL_INITIAL_REFCNT | (((Py_ssize_t)_Py_STATICALLY_ALLOCATED_FLAG) << 32)))
4347
4448#else
4549/*
@@ -54,8 +58,10 @@ immortality, but the execution would still be correct.
5458Reference count increases and decreases will first go through an immortality
5559check by comparing the reference count field to the minimum immortality refcount.
5660*/
57- #define _Py_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(3L << 29 ))
61+ #define _Py_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(5L << 28 ))
5862#define _Py_IMMORTAL_MINIMUM_REFCNT ((Py_ssize_t)(1L << 30))
63+ #define _Py_STATIC_IMMORTAL_INITIAL_REFCNT ((Py_ssize_t)(7L << 28))
64+ #define _Py_STATIC_IMMORTAL_MINIMUM_REFCNT ((Py_ssize_t)(6L << 28))
5965#endif
6066
6167// Py_GIL_DISABLED builds indicate immortal objects using `ob_ref_local`, which is
@@ -123,10 +129,21 @@ static inline Py_ALWAYS_INLINE int _Py_IsImmortal(PyObject *op)
123129#define _Py_IsImmortal (op ) _Py_IsImmortal(_PyObject_CAST(op))
124130
125131
132+ static inline Py_ALWAYS_INLINE int _Py_IsStaticImmortal (PyObject * op )
133+ {
134+ #if defined(Py_GIL_DISABLED ) || SIZEOF_VOID_P > 4
135+ return (op -> ob_flags & _Py_STATICALLY_ALLOCATED_FLAG ) != 0 ;
136+ #else
137+ return op -> ob_refcnt >= _Py_STATIC_IMMORTAL_MINIMUM_REFCNT ;
138+ #endif
139+ }
140+ #define _Py_IsStaticImmortal (op ) _Py_IsStaticImmortal(_PyObject_CAST(op))
141+
126142// Py_SET_REFCNT() implementation for stable ABI
127143PyAPI_FUNC (void ) _Py_SetRefcnt (PyObject * ob , Py_ssize_t refcnt );
128144
129145static inline void Py_SET_REFCNT (PyObject * ob , Py_ssize_t refcnt ) {
146+ assert (refcnt >= 0 );
130147#if defined(Py_LIMITED_API ) && Py_LIMITED_API + 0 >= 0x030d0000
131148 // Stable ABI implements Py_SET_REFCNT() as a function call
132149 // on limited C API version 3.13 and newer.
@@ -139,9 +156,12 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
139156 if (_Py_IsImmortal (ob )) {
140157 return ;
141158 }
142-
143159#ifndef Py_GIL_DISABLED
160+ #if SIZEOF_VOID_P > 4
161+ ob -> ob_refcnt = (PY_UINT32_T )refcnt ;
162+ #else
144163 ob -> ob_refcnt = refcnt ;
164+ #endif
145165#else
146166 if (_Py_IsOwnedByCurrentThread (ob )) {
147167 if ((size_t )refcnt > (size_t )UINT32_MAX ) {
@@ -252,13 +272,13 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
252272 _Py_atomic_add_ssize (& op -> ob_ref_shared , (1 << _Py_REF_SHARED_SHIFT ));
253273 }
254274#elif SIZEOF_VOID_P > 4
255- PY_UINT32_T cur_refcnt = op -> ob_refcnt_split [ PY_BIG_ENDIAN ] ;
275+ PY_UINT32_T cur_refcnt = op -> ob_refcnt ;
256276 if (((int32_t )cur_refcnt ) < 0 ) {
257277 // the object is immortal
258278 _Py_INCREF_IMMORTAL_STAT_INC ();
259279 return ;
260280 }
261- op -> ob_refcnt_split [ PY_BIG_ENDIAN ] = cur_refcnt + 1 ;
281+ op -> ob_refcnt = cur_refcnt + 1 ;
262282#else
263283 if (_Py_IsImmortal (op )) {
264284 _Py_INCREF_IMMORTAL_STAT_INC ();
@@ -354,7 +374,13 @@ static inline void Py_DECREF(PyObject *op)
354374#elif defined(Py_REF_DEBUG )
355375static inline void Py_DECREF (const char * filename , int lineno , PyObject * op )
356376{
377+ #if SIZEOF_VOID_P > 4
378+ /* If an object has been freed, it will have a negative full refcnt
379+ * If it has not it been freed, will have a very large refcnt */
380+ if (op -> ob_refcnt_full <= 0 || op -> ob_refcnt > (UINT32_MAX - (1 <<20 ))) {
381+ #else
357382 if (op -> ob_refcnt <= 0 ) {
383+ #endif
358384 _Py_NegativeRefcount (filename , lineno , op );
359385 }
360386 if (_Py_IsImmortal (op )) {
0 commit comments