mirror of https://github.com/python/cpython
gh-102304: Consolidate Direct Usage of _Py_RefTotal (gh-102514)
This simplifies further changes to _Py_RefTotal (e.g. make it atomic or move it to PyInterpreterState). https://github.com/python/cpython/issues/102304
This commit is contained in:
parent
11a2c6ce51
commit
cbb0aa71d0
|
@ -3,6 +3,7 @@
|
|||
#endif
|
||||
|
||||
PyAPI_FUNC(void) _Py_NewReference(PyObject *op);
|
||||
PyAPI_FUNC(void) _Py_NewReferenceNoTotal(PyObject *op);
|
||||
|
||||
#ifdef Py_TRACE_REFS
|
||||
/* Py_TRACE_REFS is such major surgery that we call external routines. */
|
||||
|
|
|
@ -37,11 +37,23 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
|
|||
#define _Py_FatalRefcountError(message) \
|
||||
_Py_FatalRefcountErrorFunc(__func__, (message))
|
||||
|
||||
|
||||
#ifdef Py_REF_DEBUG
|
||||
/* The symbol is only exposed in the API for the sake of extensions
|
||||
built against the pre-3.12 stable ABI. */
|
||||
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
|
||||
|
||||
extern void _Py_AddRefTotal(Py_ssize_t);
|
||||
extern void _Py_IncRefTotal(void);
|
||||
extern void _Py_DecRefTotal(void);
|
||||
# define _Py_DEC_REFTOTAL() _Py_RefTotal--
|
||||
#endif
|
||||
|
||||
// Increment reference count by n
|
||||
static inline void _Py_RefcntAdd(PyObject* op, Py_ssize_t n)
|
||||
{
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal += n;
|
||||
_Py_AddRefTotal(n);
|
||||
#endif
|
||||
op->ob_refcnt += n;
|
||||
}
|
||||
|
@ -52,7 +64,7 @@ _Py_DECREF_SPECIALIZED(PyObject *op, const destructor destruct)
|
|||
{
|
||||
_Py_DECREF_STAT_INC();
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
_Py_DEC_REFTOTAL();
|
||||
#endif
|
||||
if (--op->ob_refcnt != 0) {
|
||||
assert(op->ob_refcnt > 0);
|
||||
|
@ -70,7 +82,7 @@ _Py_DECREF_NO_DEALLOC(PyObject *op)
|
|||
{
|
||||
_Py_DECREF_STAT_INC();
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
_Py_DEC_REFTOTAL();
|
||||
#endif
|
||||
op->ob_refcnt--;
|
||||
#ifdef Py_DEBUG
|
||||
|
@ -80,6 +92,11 @@ _Py_DECREF_NO_DEALLOC(PyObject *op)
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef Py_REF_DEBUG
|
||||
# undef _Py_DEC_REFTOTAL
|
||||
#endif
|
||||
|
||||
|
||||
PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type);
|
||||
PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content);
|
||||
|
||||
|
|
|
@ -490,7 +490,21 @@ you can count such references to the type object.)
|
|||
*/
|
||||
|
||||
#ifdef Py_REF_DEBUG
|
||||
PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
|
||||
# if defined(Py_LIMITED_API) && Py_LIMITED_API+0 < 0x030A0000
|
||||
extern Py_ssize_t _Py_RefTotal;
|
||||
# define _Py_INC_REFTOTAL() _Py_RefTotal++
|
||||
# define _Py_DEC_REFTOTAL() _Py_RefTotal--
|
||||
# elif defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||
extern void _Py_IncRefTotal(void);
|
||||
extern void _Py_DecRefTotal(void);
|
||||
# define _Py_INC_REFTOTAL() _Py_IncRefTotal()
|
||||
# define _Py_DEC_REFTOTAL() _Py_DecRefTotal()
|
||||
# elif !defined(Py_LIMITED_API) || Py_LIMITED_API+0 > 0x030C0000
|
||||
extern void _Py_IncRefTotal_DO_NOT_USE_THIS(void);
|
||||
extern void _Py_DecRefTotal_DO_NOT_USE_THIS(void);
|
||||
# define _Py_INC_REFTOTAL() _Py_IncRefTotal_DO_NOT_USE_THIS()
|
||||
# define _Py_DEC_REFTOTAL() _Py_DecRefTotal_DO_NOT_USE_THIS()
|
||||
# endif
|
||||
PyAPI_FUNC(void) _Py_NegativeRefcount(const char *filename, int lineno,
|
||||
PyObject *op);
|
||||
#endif /* Py_REF_DEBUG */
|
||||
|
@ -519,8 +533,8 @@ static inline void Py_INCREF(PyObject *op)
|
|||
// Non-limited C API and limited C API for Python 3.9 and older access
|
||||
// directly PyObject.ob_refcnt.
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal++;
|
||||
#endif
|
||||
_Py_INC_REFTOTAL();
|
||||
#endif // Py_REF_DEBUG
|
||||
op->ob_refcnt++;
|
||||
#endif
|
||||
}
|
||||
|
@ -539,7 +553,7 @@ static inline void Py_DECREF(PyObject *op) {
|
|||
static inline void Py_DECREF(const char *filename, int lineno, PyObject *op)
|
||||
{
|
||||
_Py_DECREF_STAT_INC();
|
||||
_Py_RefTotal--;
|
||||
_Py_DEC_REFTOTAL();
|
||||
if (--op->ob_refcnt != 0) {
|
||||
if (op->ob_refcnt < 0) {
|
||||
_Py_NegativeRefcount(filename, lineno, op);
|
||||
|
@ -564,6 +578,9 @@ static inline void Py_DECREF(PyObject *op)
|
|||
#define Py_DECREF(op) Py_DECREF(_PyObject_CAST(op))
|
||||
#endif
|
||||
|
||||
#undef _Py_INC_REFTOTAL
|
||||
#undef _Py_DEC_REFTOTAL
|
||||
|
||||
|
||||
/* Safely decref `op` and set `op` to NULL, especially useful in tp_clear
|
||||
* and tp_dealloc implementations.
|
||||
|
|
|
@ -1654,15 +1654,10 @@ slot_tp_del(PyObject *self)
|
|||
*/
|
||||
{
|
||||
Py_ssize_t refcnt = Py_REFCNT(self);
|
||||
_Py_NewReference(self);
|
||||
_Py_NewReferenceNoTotal(self);
|
||||
Py_SET_REFCNT(self, refcnt);
|
||||
}
|
||||
assert(!PyType_IS_GC(Py_TYPE(self)) || PyObject_GC_IsTracked(self));
|
||||
/* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased
|
||||
_Py_RefTotal, so we need to undo that. */
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
#endif
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
|
|
|
@ -3060,21 +3060,20 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
|
|||
Py_DECREF(v);
|
||||
return 0;
|
||||
}
|
||||
/* XXX UNREF/NEWREF interface should be more symmetrical */
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
#endif
|
||||
#ifdef Py_TRACE_REFS
|
||||
_Py_ForgetReference(v);
|
||||
#endif
|
||||
*pv = (PyObject *)
|
||||
PyObject_Realloc(v, PyBytesObject_SIZE + newsize);
|
||||
if (*pv == NULL) {
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_DecRefTotal();
|
||||
#endif
|
||||
PyObject_Free(v);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
_Py_NewReference(*pv);
|
||||
_Py_NewReferenceNoTotal(*pv);
|
||||
sv = (PyBytesObject *) *pv;
|
||||
Py_SET_SIZE(sv, newsize);
|
||||
sv->ob_sval[newsize] = '\0';
|
||||
|
|
|
@ -303,7 +303,7 @@ static inline void
|
|||
dictkeys_incref(PyDictKeysObject *dk)
|
||||
{
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal++;
|
||||
_Py_IncRefTotal();
|
||||
#endif
|
||||
dk->dk_refcnt++;
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ dictkeys_decref(PyDictKeysObject *dk)
|
|||
{
|
||||
assert(dk->dk_refcnt > 0);
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
_Py_DecRefTotal();
|
||||
#endif
|
||||
if (--dk->dk_refcnt == 0) {
|
||||
free_keys_object(dk);
|
||||
|
@ -633,7 +633,7 @@ new_keys_object(uint8_t log2_size, bool unicode)
|
|||
}
|
||||
}
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal++;
|
||||
_Py_IncRefTotal();
|
||||
#endif
|
||||
dk->dk_refcnt = 1;
|
||||
dk->dk_log2_size = log2_size;
|
||||
|
@ -821,7 +821,7 @@ clone_combined_dict_keys(PyDictObject *orig)
|
|||
we have it now; calling dictkeys_incref would be an error as
|
||||
keys->dk_refcnt is already set to 1 (after memcpy). */
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal++;
|
||||
_Py_IncRefTotal();
|
||||
#endif
|
||||
return keys;
|
||||
}
|
||||
|
@ -1520,7 +1520,7 @@ dictresize(PyDictObject *mp, uint8_t log2_newsize, int unicode)
|
|||
// We can not use free_keys_object here because key's reference
|
||||
// are moved already.
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
_Py_DecRefTotal();
|
||||
#endif
|
||||
if (oldkeys == Py_EMPTY_KEYS) {
|
||||
oldkeys->dk_refcnt--;
|
||||
|
|
|
@ -56,6 +56,24 @@ _PyObject_CheckConsistency(PyObject *op, int check_content)
|
|||
#ifdef Py_REF_DEBUG
|
||||
Py_ssize_t _Py_RefTotal;
|
||||
|
||||
static inline void
|
||||
reftotal_increment(void)
|
||||
{
|
||||
_Py_RefTotal++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
reftotal_decrement(void)
|
||||
{
|
||||
_Py_RefTotal--;
|
||||
}
|
||||
|
||||
void
|
||||
_Py_AddRefTotal(Py_ssize_t n)
|
||||
{
|
||||
_Py_RefTotal += n;
|
||||
}
|
||||
|
||||
Py_ssize_t
|
||||
_Py_GetRefTotal(void)
|
||||
{
|
||||
|
@ -121,6 +139,32 @@ _Py_NegativeRefcount(const char *filename, int lineno, PyObject *op)
|
|||
filename, lineno, __func__);
|
||||
}
|
||||
|
||||
/* This is exposed strictly for use in Py_INCREF(). */
|
||||
PyAPI_FUNC(void)
|
||||
_Py_IncRefTotal_DO_NOT_USE_THIS(void)
|
||||
{
|
||||
reftotal_increment();
|
||||
}
|
||||
|
||||
/* This is exposed strictly for use in Py_DECREF(). */
|
||||
PyAPI_FUNC(void)
|
||||
_Py_DecRefTotal_DO_NOT_USE_THIS(void)
|
||||
{
|
||||
reftotal_decrement();
|
||||
}
|
||||
|
||||
void
|
||||
_Py_IncRefTotal(void)
|
||||
{
|
||||
reftotal_increment();
|
||||
}
|
||||
|
||||
void
|
||||
_Py_DecRefTotal(void)
|
||||
{
|
||||
reftotal_decrement();
|
||||
}
|
||||
|
||||
#endif /* Py_REF_DEBUG */
|
||||
|
||||
void
|
||||
|
@ -138,12 +182,18 @@ Py_DecRef(PyObject *o)
|
|||
void
|
||||
_Py_IncRef(PyObject *o)
|
||||
{
|
||||
#ifdef Py_REF_DEBUG
|
||||
reftotal_increment();
|
||||
#endif
|
||||
Py_INCREF(o);
|
||||
}
|
||||
|
||||
void
|
||||
_Py_DecRef(PyObject *o)
|
||||
{
|
||||
#ifdef Py_REF_DEBUG
|
||||
reftotal_decrement();
|
||||
#endif
|
||||
Py_DECREF(o);
|
||||
}
|
||||
|
||||
|
@ -238,17 +288,12 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
|
|||
/* tp_finalize resurrected it! Make it look like the original Py_DECREF
|
||||
* never happened. */
|
||||
Py_ssize_t refcnt = Py_REFCNT(self);
|
||||
_Py_NewReference(self);
|
||||
_Py_NewReferenceNoTotal(self);
|
||||
Py_SET_REFCNT(self, refcnt);
|
||||
|
||||
_PyObject_ASSERT(self,
|
||||
(!_PyType_IS_GC(Py_TYPE(self))
|
||||
|| _PyObject_GC_IS_TRACKED(self)));
|
||||
/* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased
|
||||
_Py_RefTotal, so we need to undo that. */
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2010,21 +2055,33 @@ _PyTypes_FiniTypes(PyInterpreterState *interp)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
_Py_NewReference(PyObject *op)
|
||||
static inline void
|
||||
new_reference(PyObject *op)
|
||||
{
|
||||
if (_PyRuntime.tracemalloc.config.tracing) {
|
||||
_PyTraceMalloc_NewReference(op);
|
||||
}
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal++;
|
||||
#endif
|
||||
Py_SET_REFCNT(op, 1);
|
||||
#ifdef Py_TRACE_REFS
|
||||
_Py_AddToAllObjects(op, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_Py_NewReference(PyObject *op)
|
||||
{
|
||||
#ifdef Py_REF_DEBUG
|
||||
reftotal_increment();
|
||||
#endif
|
||||
new_reference(op);
|
||||
}
|
||||
|
||||
void
|
||||
_Py_NewReferenceNoTotal(PyObject *op)
|
||||
{
|
||||
new_reference(op);
|
||||
}
|
||||
|
||||
|
||||
#ifdef Py_TRACE_REFS
|
||||
void
|
||||
|
|
|
@ -592,7 +592,7 @@ _PyStructSequence_FiniType(PyTypeObject *type)
|
|||
// Don't use Py_DECREF(): static type must not be deallocated
|
||||
Py_SET_REFCNT(type, 0);
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
_Py_DecRefTotal();
|
||||
#endif
|
||||
|
||||
// Make sure that _PyStructSequence_InitType() will initialize
|
||||
|
|
|
@ -930,10 +930,6 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
|
|||
return *pv == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
/* XXX UNREF/NEWREF interface should be more symmetrical */
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
#endif
|
||||
if (_PyObject_GC_IS_TRACKED(v)) {
|
||||
_PyObject_GC_UNTRACK(v);
|
||||
}
|
||||
|
@ -947,10 +943,13 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
|
|||
sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
|
||||
if (sv == NULL) {
|
||||
*pv = NULL;
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_DecRefTotal();
|
||||
#endif
|
||||
PyObject_GC_Del(v);
|
||||
return -1;
|
||||
}
|
||||
_Py_NewReference((PyObject *) sv);
|
||||
_Py_NewReferenceNoTotal((PyObject *) sv);
|
||||
/* Zero out items added by growing */
|
||||
if (newsize > oldsize)
|
||||
memset(&sv->ob_item[oldsize], 0,
|
||||
|
|
|
@ -947,21 +947,18 @@ resize_compact(PyObject *unicode, Py_ssize_t length)
|
|||
_PyUnicode_UTF8(unicode) = NULL;
|
||||
_PyUnicode_UTF8_LENGTH(unicode) = 0;
|
||||
}
|
||||
#ifdef Py_REF_DEBUG
|
||||
_Py_RefTotal--;
|
||||
#endif
|
||||
#ifdef Py_TRACE_REFS
|
||||
_Py_ForgetReference(unicode);
|
||||
#endif
|
||||
|
||||
new_unicode = (PyObject *)PyObject_Realloc(unicode, new_size);
|
||||
if (new_unicode == NULL) {
|
||||
_Py_NewReference(unicode);
|
||||
_Py_NewReferenceNoTotal(unicode);
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
unicode = new_unicode;
|
||||
_Py_NewReference(unicode);
|
||||
_Py_NewReferenceNoTotal(unicode);
|
||||
|
||||
_PyUnicode_LENGTH(unicode) = length;
|
||||
#ifdef Py_DEBUG
|
||||
|
|
Loading…
Reference in New Issue