mirror of
https://github.com/python/cpython.git
synced 2025-10-18 12:48:57 +00:00
GH-127705: Fix _Py_RefcntAdd to handle objects becoming immortal (GH-131140)
This commit is contained in:
parent
061da44bac
commit
f30376c650
3 changed files with 20 additions and 11 deletions
|
@ -135,15 +135,20 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
|
||||||
_Py_INCREF_IMMORTAL_STAT_INC();
|
_Py_INCREF_IMMORTAL_STAT_INC();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef Py_REF_DEBUG
|
#ifndef Py_GIL_DISABLED
|
||||||
_Py_AddRefTotal(_PyThreadState_GET(), n);
|
Py_ssize_t refcnt = _Py_REFCNT(op);
|
||||||
#endif
|
Py_ssize_t new_refcnt = refcnt + n;
|
||||||
#if !defined(Py_GIL_DISABLED)
|
if (new_refcnt >= (Py_ssize_t)_Py_IMMORTAL_MINIMUM_REFCNT) {
|
||||||
#if SIZEOF_VOID_P > 4
|
new_refcnt = _Py_IMMORTAL_INITIAL_REFCNT;
|
||||||
op->ob_refcnt += (PY_UINT32_T)n;
|
}
|
||||||
#else
|
# if SIZEOF_VOID_P > 4
|
||||||
op->ob_refcnt += n;
|
op->ob_refcnt = (PY_UINT32_T)new_refcnt;
|
||||||
#endif
|
# else
|
||||||
|
op->ob_refcnt = new_refcnt;
|
||||||
|
# endif
|
||||||
|
# ifdef Py_REF_DEBUG
|
||||||
|
_Py_AddRefTotal(_PyThreadState_GET(), new_refcnt - refcnt);
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
if (_Py_IsOwnedByCurrentThread(op)) {
|
if (_Py_IsOwnedByCurrentThread(op)) {
|
||||||
uint32_t local = op->ob_ref_local;
|
uint32_t local = op->ob_ref_local;
|
||||||
|
@ -160,6 +165,9 @@ static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
|
||||||
else {
|
else {
|
||||||
_Py_atomic_add_ssize(&op->ob_ref_shared, (n << _Py_REF_SHARED_SHIFT));
|
_Py_atomic_add_ssize(&op->ob_ref_shared, (n << _Py_REF_SHARED_SHIFT));
|
||||||
}
|
}
|
||||||
|
# ifdef Py_REF_DEBUG
|
||||||
|
_Py_AddRefTotal(_PyThreadState_GET(), n);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
// Although the ref count was increased by `n` (which may be greater than 1)
|
// Although the ref count was increased by `n` (which may be greater than 1)
|
||||||
// it is only a single increment (i.e. addition) operation, so only 1 refcnt
|
// it is only a single increment (i.e. addition) operation, so only 1 refcnt
|
||||||
|
|
|
@ -42,7 +42,8 @@ beyond the refcount limit. Immortality checks for reference count decreases will
|
||||||
be done by checking the bit sign flag in the lower 32 bits.
|
be done by checking the bit sign flag in the lower 32 bits.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#define _Py_IMMORTAL_INITIAL_REFCNT (3UL << 30)
|
#define _Py_IMMORTAL_INITIAL_REFCNT (3ULL << 30)
|
||||||
|
#define _Py_IMMORTAL_MINIMUM_REFCNT (1ULL << 31)
|
||||||
#define _Py_STATIC_FLAG_BITS ((Py_ssize_t)(_Py_STATICALLY_ALLOCATED_FLAG | _Py_IMMORTAL_FLAGS))
|
#define _Py_STATIC_FLAG_BITS ((Py_ssize_t)(_Py_STATICALLY_ALLOCATED_FLAG | _Py_IMMORTAL_FLAGS))
|
||||||
#define _Py_STATIC_IMMORTAL_INITIAL_REFCNT (((Py_ssize_t)_Py_IMMORTAL_INITIAL_REFCNT) | (_Py_STATIC_FLAG_BITS << 48))
|
#define _Py_STATIC_IMMORTAL_INITIAL_REFCNT (((Py_ssize_t)_Py_IMMORTAL_INITIAL_REFCNT) | (_Py_STATIC_FLAG_BITS << 48))
|
||||||
|
|
||||||
|
|
|
@ -15982,7 +15982,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
|
||||||
case SSTATE_INTERNED_MORTAL:
|
case SSTATE_INTERNED_MORTAL:
|
||||||
// Restore 2 references held by the interned dict; these will
|
// Restore 2 references held by the interned dict; these will
|
||||||
// be decref'd by clear_interned_dict's PyDict_Clear.
|
// be decref'd by clear_interned_dict's PyDict_Clear.
|
||||||
Py_SET_REFCNT(s, Py_REFCNT(s) + 2);
|
_Py_RefcntAdd(s, 2);
|
||||||
#ifdef Py_REF_DEBUG
|
#ifdef Py_REF_DEBUG
|
||||||
/* let's be pedantic with the ref total */
|
/* let's be pedantic with the ref total */
|
||||||
_Py_IncRefTotal(_PyThreadState_GET());
|
_Py_IncRefTotal(_PyThreadState_GET());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue