bpo-39573: Add Py_SET_REFCNT() function (GH-18389)
Add a Py_SET_REFCNT() function to set the reference counter of an object.
This commit is contained in:
parent
a93c51e3a8
commit
c86a11221d
|
@ -79,6 +79,13 @@ the definition of all other Python objects.
|
||||||
(((PyObject*)(o))->ob_refcnt)
|
(((PyObject*)(o))->ob_refcnt)
|
||||||
|
|
||||||
|
|
||||||
|
.. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)
|
||||||
|
|
||||||
|
Set the object *o* reference counter to *refcnt*.
|
||||||
|
|
||||||
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
|
||||||
.. c:macro:: Py_SIZE(o)
|
.. c:macro:: Py_SIZE(o)
|
||||||
|
|
||||||
This macro is used to access the :attr:`ob_size` member of a Python object.
|
This macro is used to access the :attr:`ob_size` member of a Python object.
|
||||||
|
|
|
@ -123,6 +123,11 @@ typedef struct {
|
||||||
#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type)
|
#define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type)
|
||||||
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
|
#define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size)
|
||||||
|
|
||||||
|
static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) {
|
||||||
|
ob->ob_refcnt = refcnt;
|
||||||
|
}
|
||||||
|
#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Type objects contain a string containing the type name (to help somewhat
|
Type objects contain a string containing the type name (to help somewhat
|
||||||
in debugging), the allocation parameters (see PyObject_New() and
|
in debugging), the allocation parameters (see PyObject_New() and
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Add a :c:func:`Py_SET_REFCNT` function to set the reference counter of an
|
||||||
|
object.
|
|
@ -3551,7 +3551,7 @@ slot_tp_del(PyObject *self)
|
||||||
|
|
||||||
/* Temporarily resurrect the object. */
|
/* Temporarily resurrect the object. */
|
||||||
assert(Py_REFCNT(self) == 0);
|
assert(Py_REFCNT(self) == 0);
|
||||||
Py_REFCNT(self) = 1;
|
Py_SET_REFCNT(self, 1);
|
||||||
|
|
||||||
/* Save the current exception, if any. */
|
/* Save the current exception, if any. */
|
||||||
PyErr_Fetch(&error_type, &error_value, &error_traceback);
|
PyErr_Fetch(&error_type, &error_value, &error_traceback);
|
||||||
|
@ -3574,7 +3574,8 @@ slot_tp_del(PyObject *self)
|
||||||
* cause a recursive call.
|
* cause a recursive call.
|
||||||
*/
|
*/
|
||||||
assert(Py_REFCNT(self) > 0);
|
assert(Py_REFCNT(self) > 0);
|
||||||
if (--Py_REFCNT(self) == 0) {
|
Py_SET_REFCNT(self, Py_REFCNT(self) - 1);
|
||||||
|
if (Py_REFCNT(self) == 0) {
|
||||||
/* this is the normal path out */
|
/* this is the normal path out */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3585,7 +3586,7 @@ slot_tp_del(PyObject *self)
|
||||||
{
|
{
|
||||||
Py_ssize_t refcnt = Py_REFCNT(self);
|
Py_ssize_t refcnt = Py_REFCNT(self);
|
||||||
_Py_NewReference(self);
|
_Py_NewReference(self);
|
||||||
Py_REFCNT(self) = refcnt;
|
Py_SET_REFCNT(self, refcnt);
|
||||||
}
|
}
|
||||||
assert(!PyType_IS_GC(Py_TYPE(self)) || _PyObject_GC_IS_TRACKED(self));
|
assert(!PyType_IS_GC(Py_TYPE(self)) || _PyObject_GC_IS_TRACKED(self));
|
||||||
/* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased
|
/* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased
|
||||||
|
@ -4621,7 +4622,7 @@ check_pyobject_uninitialized_is_freed(PyObject *self, PyObject *Py_UNUSED(args))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Initialize reference count to avoid early crash in ceval or GC */
|
/* Initialize reference count to avoid early crash in ceval or GC */
|
||||||
Py_REFCNT(op) = 1;
|
Py_SET_REFCNT(op, 1);
|
||||||
/* object fields like ob_type are uninitialized! */
|
/* object fields like ob_type are uninitialized! */
|
||||||
return test_pyobject_is_freed("check_pyobject_uninitialized_is_freed", op);
|
return test_pyobject_is_freed("check_pyobject_uninitialized_is_freed", op);
|
||||||
}
|
}
|
||||||
|
@ -4636,7 +4637,7 @@ check_pyobject_forbidden_bytes_is_freed(PyObject *self, PyObject *Py_UNUSED(args
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Initialize reference count to avoid early crash in ceval or GC */
|
/* Initialize reference count to avoid early crash in ceval or GC */
|
||||||
Py_REFCNT(op) = 1;
|
Py_SET_REFCNT(op, 1);
|
||||||
/* ob_type field is after the memory block: part of "forbidden bytes"
|
/* ob_type field is after the memory block: part of "forbidden bytes"
|
||||||
when using debug hooks on memory allocators! */
|
when using debug hooks on memory allocators! */
|
||||||
return test_pyobject_is_freed("check_pyobject_forbidden_bytes_is_freed", op);
|
return test_pyobject_is_freed("check_pyobject_forbidden_bytes_is_freed", op);
|
||||||
|
@ -4652,7 +4653,7 @@ check_pyobject_freed_is_freed(PyObject *self, PyObject *Py_UNUSED(args))
|
||||||
}
|
}
|
||||||
Py_TYPE(op)->tp_dealloc(op);
|
Py_TYPE(op)->tp_dealloc(op);
|
||||||
/* Reset reference count to avoid early crash in ceval or GC */
|
/* Reset reference count to avoid early crash in ceval or GC */
|
||||||
Py_REFCNT(op) = 1;
|
Py_SET_REFCNT(op, 1);
|
||||||
/* object memory is freed! */
|
/* object memory is freed! */
|
||||||
return test_pyobject_is_freed("check_pyobject_freed_is_freed", op);
|
return test_pyobject_is_freed("check_pyobject_freed_is_freed", op);
|
||||||
}
|
}
|
||||||
|
@ -5134,7 +5135,7 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args))
|
||||||
}
|
}
|
||||||
assert(Py_REFCNT(obj) == 1);
|
assert(Py_REFCNT(obj) == 1);
|
||||||
|
|
||||||
Py_REFCNT(obj) = 0;
|
Py_SET_REFCNT(obj, 0);
|
||||||
/* Py_DECREF() must call _Py_NegativeRefcount() and abort Python */
|
/* Py_DECREF() must call _Py_NegativeRefcount() and abort Python */
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ PyModuleDef_Init(struct PyModuleDef* def)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (def->m_base.m_index == 0) {
|
if (def->m_base.m_index == 0) {
|
||||||
max_module_number++;
|
max_module_number++;
|
||||||
Py_REFCNT(def) = 1;
|
Py_SET_REFCNT(def, 1);
|
||||||
Py_TYPE(def) = &PyModuleDef_Type;
|
Py_TYPE(def) = &PyModuleDef_Type;
|
||||||
def->m_base.m_index = max_module_number;
|
def->m_base.m_index = max_module_number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Temporarily resurrect the object. */
|
/* Temporarily resurrect the object. */
|
||||||
Py_REFCNT(self) = 1;
|
Py_SET_REFCNT(self, 1);
|
||||||
|
|
||||||
PyObject_CallFinalizer(self);
|
PyObject_CallFinalizer(self);
|
||||||
|
|
||||||
|
@ -223,7 +223,8 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
|
||||||
|
|
||||||
/* Undo the temporary resurrection; can't use DECREF here, it would
|
/* Undo the temporary resurrection; can't use DECREF here, it would
|
||||||
* cause a recursive call. */
|
* cause a recursive call. */
|
||||||
if (--Py_REFCNT(self) == 0) {
|
Py_SET_REFCNT(self, Py_REFCNT(self) - 1);
|
||||||
|
if (Py_REFCNT(self) == 0) {
|
||||||
return 0; /* this is the normal path out */
|
return 0; /* this is the normal path out */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
|
||||||
* never happened. */
|
* never happened. */
|
||||||
Py_ssize_t refcnt = Py_REFCNT(self);
|
Py_ssize_t refcnt = Py_REFCNT(self);
|
||||||
_Py_NewReference(self);
|
_Py_NewReference(self);
|
||||||
Py_REFCNT(self) = refcnt;
|
Py_SET_REFCNT(self, refcnt);
|
||||||
|
|
||||||
_PyObject_ASSERT(self,
|
_PyObject_ASSERT(self,
|
||||||
(!PyType_IS_GC(Py_TYPE(self))
|
(!PyType_IS_GC(Py_TYPE(self))
|
||||||
|
@ -1818,7 +1819,7 @@ _Py_NewReference(PyObject *op)
|
||||||
#ifdef Py_REF_DEBUG
|
#ifdef Py_REF_DEBUG
|
||||||
_Py_RefTotal++;
|
_Py_RefTotal++;
|
||||||
#endif
|
#endif
|
||||||
Py_REFCNT(op) = 1;
|
Py_SET_REFCNT(op, 1);
|
||||||
#ifdef Py_TRACE_REFS
|
#ifdef Py_TRACE_REFS
|
||||||
_Py_AddToAllObjects(op, 1);
|
_Py_AddToAllObjects(op, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1903,7 +1903,7 @@ unicode_dealloc(PyObject *unicode)
|
||||||
|
|
||||||
case SSTATE_INTERNED_MORTAL:
|
case SSTATE_INTERNED_MORTAL:
|
||||||
/* revive dead object temporarily for DelItem */
|
/* revive dead object temporarily for DelItem */
|
||||||
Py_REFCNT(unicode) = 3;
|
Py_SET_REFCNT(unicode, 3);
|
||||||
if (PyDict_DelItem(interned, unicode) != 0) {
|
if (PyDict_DelItem(interned, unicode) != 0) {
|
||||||
_PyErr_WriteUnraisableMsg("deletion of interned string failed",
|
_PyErr_WriteUnraisableMsg("deletion of interned string failed",
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -15367,7 +15367,7 @@ PyUnicode_InternInPlace(PyObject **p)
|
||||||
}
|
}
|
||||||
/* The two references in interned are not counted by refcnt.
|
/* The two references in interned are not counted by refcnt.
|
||||||
The deallocator will take care of this */
|
The deallocator will take care of this */
|
||||||
Py_REFCNT(s) -= 2;
|
Py_SET_REFCNT(s, Py_REFCNT(s) - 2);
|
||||||
_PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL;
|
_PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue