@@ -88,7 +88,7 @@ having all the lower 32 bits set, which will avoid the reference count to go
88
88
beyond the refcount limit. Immortality checks for reference count decreases will
89
89
be done by checking the bit sign flag in the lower 32 bits.
90
90
*/
91
- #define _Py_IMMORTAL_REFCNT UINT_MAX
91
+ #define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX)
92
92
93
93
#else
94
94
/*
@@ -103,7 +103,7 @@ immortality, but the execution would still be correct.
103
103
Reference count increases and decreases will first go through an immortality
104
104
check by comparing the reference count field to the immortality reference count.
105
105
*/
106
- #define _Py_IMMORTAL_REFCNT ( UINT_MAX >> 2)
106
+ #define _Py_IMMORTAL_REFCNT _Py_CAST(Py_ssize_t, UINT_MAX >> 2)
107
107
#endif
108
108
109
109
// 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) {
317
317
static inline Py_ALWAYS_INLINE int _Py_IsImmortal (PyObject * op )
318
318
{
319
319
#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 ) ;
321
321
#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 ) ;
323
323
#else
324
- return op -> ob_refcnt == _Py_IMMORTAL_REFCNT ;
324
+ return ( op -> ob_refcnt == _Py_IMMORTAL_REFCNT ) ;
325
325
#endif
326
326
}
327
327
#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) {
350
350
if (_Py_IsImmortal (ob )) {
351
351
return ;
352
352
}
353
+
353
354
#ifndef Py_GIL_DISABLED
354
355
ob -> ob_refcnt = refcnt ;
355
356
#else
356
357
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
+ }
362
370
}
363
371
else {
364
372
// 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)
750
758
uint32_t local = _Py_atomic_load_uint32_relaxed (& op -> ob_ref_local );
751
759
uint32_t new_local = local + 1 ;
752
760
if (new_local == 0 ) {
761
+ // local is equal to _Py_IMMORTAL_REFCNT: do nothing
753
762
return ;
754
763
}
755
764
if (_Py_IsOwnedByCurrentThread (op )) {
@@ -763,6 +772,8 @@ static inline Py_ALWAYS_INLINE void Py_INCREF(PyObject *op)
763
772
PY_UINT32_T cur_refcnt = op -> ob_refcnt_split [PY_BIG_ENDIAN ];
764
773
PY_UINT32_T new_refcnt = cur_refcnt + 1 ;
765
774
if (new_refcnt == 0 ) {
775
+ // cur_refcnt is equal to _Py_IMMORTAL_REFCNT: the object is immortal,
776
+ // do nothing
766
777
return ;
767
778
}
768
779
op -> ob_refcnt_split [PY_BIG_ENDIAN ] = new_refcnt ;
0 commit comments