@@ -88,7 +88,7 @@ having all the lower 32 bits set, which will avoid the reference count to go
8888beyond the refcount limit. Immortality checks for reference count decreases will
8989be done by checking the bit sign flag in the lower 32 bits.
9090*/
91- #define _Py_IMMORTAL_REFCNT UINT_MAX
91+ #define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX)
9292
9393#else
9494/*
@@ -103,7 +103,7 @@ immortality, but the execution would still be correct.
103103Reference count increases and decreases will first go through an immortality
104104check by comparing the reference count field to the immortality reference count.
105105*/
106- #define _Py_IMMORTAL_REFCNT ( UINT_MAX >> 2)
106+ #define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX >> 2)
107107#endif
108108
109109// Py_GIL_DISABLED builds indicate immortal objects using `ob_ref_local`, which is
@@ -317,11 +317,11 @@ static inline Py_ssize_t Py_SIZE(PyObject *ob) {
317317static inline Py_ALWAYS_INLINE int _Py_IsImmortal (PyObject * op )
318318{
319319#if defined(Py_GIL_DISABLED )
320- return op -> ob_ref_local == _Py_IMMORTAL_REFCNT_LOCAL ;
320+ return ( op -> ob_ref_local == _Py_IMMORTAL_REFCNT_LOCAL ) ;
321321#elif SIZEOF_VOID_P > 4
322- return _Py_CAST (PY_INT32_T , op -> ob_refcnt ) < 0 ;
322+ return ( _Py_CAST (PY_INT32_T , op -> ob_refcnt ) < 0 ) ;
323323#else
324- return op -> ob_refcnt == _Py_IMMORTAL_REFCNT ;
324+ return ( op -> ob_refcnt == _Py_IMMORTAL_REFCNT ) ;
325325#endif
326326}
327327#define _Py_IsImmortal (op ) _Py_IsImmortal(_PyObject_CAST(op))
@@ -350,15 +350,23 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
350350 if (_Py_IsImmortal (ob )) {
351351 return ;
352352 }
353+
353354#ifndef Py_GIL_DISABLED
354355 ob -> ob_refcnt = refcnt ;
355356#else
356357 if (_Py_IsOwnedByCurrentThread (ob )) {
357- // Set local refcount to desired refcount and shared refcount to zero,
358- // but preserve the shared refcount flags.
359- assert (refcnt < UINT32_MAX );
360- ob -> ob_ref_local = _Py_STATIC_CAST (uint32_t , refcnt );
361- ob -> ob_ref_shared &= _Py_REF_SHARED_FLAG_MASK ;
358+ if ((size_t )refcnt > (size_t )UINT32_MAX ) {
359+ // On overflow, make the object immortal
360+ op -> ob_tid = _Py_UNOWNED_TID ;
361+ op -> ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL ;
362+ op -> ob_ref_shared = 0 ;
363+ }
364+ else {
365+ // Set local refcount to desired refcount and shared refcount
366+ // to zero, but preserve the shared refcount flags.
367+ ob -> ob_ref_local = _Py_STATIC_CAST (uint32_t , refcnt );
368+ ob -> ob_ref_shared &= _Py_REF_SHARED_FLAG_MASK ;
369+ }
362370 }
363371 else {
364372 // Set local refcount to zero and shared refcount to desired refcount.
@@ -750,6 +758,7 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
750758 uint32_t local = _Py_atomic_load_uint32_relaxed (& op -> ob_ref_local );
751759 uint32_t new_local = local + 1 ;
752760 if (new_local == 0 ) {
761+ // local is equal to _Py_IMMORTAL_REFCNT: do nothing
753762 return ;
754763 }
755764 if (_Py_IsOwnedByCurrentThread (op )) {
@@ -763,6 +772,8 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
763772 PY_UINT32_T cur_refcnt = op -> ob_refcnt_split [PY_BIG_ENDIAN ];
764773 PY_UINT32_T new_refcnt = cur_refcnt + 1 ;
765774 if (new_refcnt == 0 ) {
775+ // cur_refcnt is equal to _Py_IMMORTAL_REFCNT: the object is immortal,
776+ // do nothing
766777 return ;
767778 }
768779 op -> ob_refcnt_split [PY_BIG_ENDIAN ] = new_refcnt ;
0 commit comments