]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39573: Add Py_SET_REFCNT() function (GH-18389)
authorVictor Stinner <vstinner@python.org>
Fri, 7 Feb 2020 00:24:29 +0000 (01:24 +0100)
committerGitHub <noreply@github.com>
Fri, 7 Feb 2020 00:24:29 +0000 (01:24 +0100)
Add a Py_SET_REFCNT() function to set the reference counter of an
object.

Doc/c-api/structures.rst
Include/object.h
Misc/NEWS.d/next/C API/2020-02-07-00-23-44.bpo-39573.nRD1q7.rst [new file with mode: 0644]
Modules/_testcapimodule.c
Objects/moduleobject.c
Objects/object.c
Objects/unicodeobject.c

index 0c661389021eff92edc10dd8827327926dec42a5..100573c5693fcdd4b073e138e30ae460de8bebde 100644 (file)
@@ -79,6 +79,13 @@ the definition of all other Python objects.
       (((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)
 
    This macro is used to access the :attr:`ob_size` member of a Python object.
index 38794a0e98cea881f38aa729fab57da80fd4afd8..0b630513375d37ce0ed3f0490043773513c112bc 100644 (file)
@@ -123,6 +123,11 @@ typedef struct {
 #define Py_TYPE(ob)             (_PyObject_CAST(ob)->ob_type)
 #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
 in debugging), the allocation parameters (see PyObject_New() and
diff --git a/Misc/NEWS.d/next/C API/2020-02-07-00-23-44.bpo-39573.nRD1q7.rst b/Misc/NEWS.d/next/C API/2020-02-07-00-23-44.bpo-39573.nRD1q7.rst
new file mode 100644 (file)
index 0000000..310933a
--- /dev/null
@@ -0,0 +1,2 @@
+Add a :c:func:`Py_SET_REFCNT` function to set the reference counter of an
+object.
index 27db86a70b9d5cd6772ec64d244872ba1f4761bb..d8bf3735046c1a5c6ad23849a79fff55581678d1 100644 (file)
@@ -3551,7 +3551,7 @@ slot_tp_del(PyObject *self)
 
     /* Temporarily resurrect the object. */
     assert(Py_REFCNT(self) == 0);
-    Py_REFCNT(self) = 1;
+    Py_SET_REFCNT(self, 1);
 
     /* Save the current exception, if any. */
     PyErr_Fetch(&error_type, &error_value, &error_traceback);
@@ -3574,7 +3574,8 @@ slot_tp_del(PyObject *self)
      * cause a recursive call.
      */
     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 */
         return;
     }
@@ -3585,7 +3586,7 @@ slot_tp_del(PyObject *self)
     {
         Py_ssize_t refcnt = Py_REFCNT(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));
     /* 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;
     }
     /* 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! */
     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;
     }
     /* 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"
        when using debug hooks on memory allocators! */
     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);
     /* Reset reference count to avoid early crash in ceval or GC */
-    Py_REFCNT(op) = 1;
+    Py_SET_REFCNT(op, 1);
     /* object memory is freed! */
     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);
 
-    Py_REFCNT(obj) = 0;
+    Py_SET_REFCNT(obj,  0);
     /* Py_DECREF() must call _Py_NegativeRefcount() and abort Python */
     Py_DECREF(obj);
 
index 49cfd574d56646aa709023f6b1b00219ea3c6170..da329b4fbac8b5830b4fd2cbc6f4ba8605a24574 100644 (file)
@@ -51,7 +51,7 @@ PyModuleDef_Init(struct PyModuleDef* def)
          return NULL;
     if (def->m_base.m_index == 0) {
         max_module_number++;
-        Py_REFCNT(def) = 1;
+        Py_SET_REFCNT(def, 1);
         Py_TYPE(def) = &PyModuleDef_Type;
         def->m_base.m_index = max_module_number;
     }
index f9682fe5b1f52876fd23fd5a135b430b9f187f91..aca20e8d096f8b07e749d08a8de5fdaa07b8bdb2 100644 (file)
@@ -213,7 +213,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
     }
 
     /* Temporarily resurrect the object. */
-    Py_REFCNT(self) = 1;
+    Py_SET_REFCNT(self, 1);
 
     PyObject_CallFinalizer(self);
 
@@ -223,7 +223,8 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
 
     /* Undo the temporary resurrection; can't use DECREF here, it would
      * 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 */
     }
 
@@ -231,7 +232,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
      * never happened. */
     Py_ssize_t refcnt = Py_REFCNT(self);
     _Py_NewReference(self);
-    Py_REFCNT(self) = refcnt;
+    Py_SET_REFCNT(self, refcnt);
 
     _PyObject_ASSERT(self,
                      (!PyType_IS_GC(Py_TYPE(self))
@@ -1818,7 +1819,7 @@ _Py_NewReference(PyObject *op)
 #ifdef Py_REF_DEBUG
     _Py_RefTotal++;
 #endif
-    Py_REFCNT(op) = 1;
+    Py_SET_REFCNT(op, 1);
 #ifdef Py_TRACE_REFS
     _Py_AddToAllObjects(op, 1);
 #endif
index 7c8bc06252a1ec1c57ada4ee45d223cda6493be7..fa48ee1ac78f0bdb90c0e912bc0937e0c9cbc738 100644 (file)
@@ -1903,7 +1903,7 @@ unicode_dealloc(PyObject *unicode)
 
     case SSTATE_INTERNED_MORTAL:
         /* revive dead object temporarily for DelItem */
-        Py_REFCNT(unicode) = 3;
+        Py_SET_REFCNT(unicode, 3);
         if (PyDict_DelItem(interned, unicode) != 0) {
             _PyErr_WriteUnraisableMsg("deletion of interned string failed",
                                       NULL);
@@ -15367,7 +15367,7 @@ PyUnicode_InternInPlace(PyObject **p)
     }
     /* The two references in interned are not counted by refcnt.
        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;
 }