[Python-checkins] bpo-39573: Convert Py_REFCNT and Py_SIZE to functions (GH-20429)

Victor Stinner webhook-mailer at python.org
Wed May 27 08:55:16 EDT 2020


https://github.com/python/cpython/commit/fe2978b3b940fe2478335e3a2ca5ad22338cdf9c
commit: fe2978b3b940fe2478335e3a2ca5ad22338cdf9c
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-05-27T14:55:10+02:00
summary:

bpo-39573: Convert Py_REFCNT and Py_SIZE to functions (GH-20429)

Convert Py_REFCNT() and Py_SIZE() macros to static inline functions.
They cannot be used as l-value anymore: use Py_SET_REFCNT() and
Py_SET_SIZE() to set an object reference count and size.

Replace &Py_SIZE(self) with &((PyVarObject*)self)->ob_size
in arraymodule.c.

This change is backward incompatible on purpose, to prepare the C API
for an opaque PyObject structure.

files:
A Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst
M Doc/c-api/structures.rst
M Doc/whatsnew/3.10.rst
M Include/object.h
M Modules/arraymodule.c
M Objects/tupleobject.c

diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst
index 5535f42ac120a..b2392fa5e19c5 100644
--- a/Doc/c-api/structures.rst
+++ b/Doc/c-api/structures.rst
@@ -88,13 +88,13 @@ the definition of all other Python objects.
    .. versionadded:: 3.9
 
 
-.. c:macro:: Py_REFCNT(o)
+.. c:function:: Py_ssize_t Py_REFCNT(const PyObject *o)
 
-   This macro is used to access the :attr:`ob_refcnt` member of a Python
-   object.
-   It expands to::
+   Get the reference count of the Python object *o*.
 
-      (((PyObject*)(o))->ob_refcnt)
+   .. versionchanged:: 3.10
+      :c:func:`Py_REFCNT()` is changed to the inline static function.
+      Use :c:func:`Py_SET_REFCNT()` to set an object reference count.
 
 
 .. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt)
@@ -104,12 +104,13 @@ the definition of all other Python objects.
    .. versionadded:: 3.9
 
 
-.. c:macro:: Py_SIZE(o)
+.. c:function:: Py_ssize_t Py_SIZE(const PyVarObject *o)
 
-   This macro is used to access the :attr:`ob_size` member of a Python object.
-   It expands to::
+   Get the size of the Python object *o*.
 
-      (((PyVarObject*)(o))->ob_size)
+   .. versionchanged:: 3.10
+      :c:func:`Py_SIZE()` is changed to the inline static function.
+      Use :c:func:`Py_SET_SIZE()` to set an object size.
 
 
 .. c:function:: void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size)
diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst
index fabd9a2463e27..9edef1ed87ba1 100644
--- a/Doc/whatsnew/3.10.rst
+++ b/Doc/whatsnew/3.10.rst
@@ -138,6 +138,15 @@ Porting to Python 3.10
   see :c:func:`Py_SET_TYPE()` (available since Python 3.9).
   (Contributed by Dong-hee Na in :issue:`39573`.)
 
+* Since :c:func:`Py_REFCNT()` is changed to the inline static function,
+  ``Py_REFCNT(obj) = new_refcnt`` must be replaced with ``Py_SET_REFCNT(obj, new_refcnt)``:
+  see :c:func:`Py_SET_REFCNT()` (available since Python 3.9).
+  (Contributed by Victor Stinner in :issue:`39573`.)
+
+* Since :c:func:`Py_SIZE()` is changed to the inline static function,
+  ``Py_SIZE(obj) = new_size`` must be replaced with ``Py_SET_SIZE(obj, new_size)``:
+  see :c:func:`Py_SET_SIZE()` (available since Python 3.9).
+  (Contributed by Victor Stinner in :issue:`39573`.)
 
 Removed
 -------
diff --git a/Include/object.h b/Include/object.h
index 5ad05699bb45c..537567040f987 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -119,30 +119,45 @@ typedef struct {
 
 /* Cast argument to PyVarObject* type. */
 #define _PyVarObject_CAST(op) ((PyVarObject*)(op))
+#define _PyVarObject_CAST_CONST(op) ((const PyVarObject*)(op))
+
+
+static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) {
+    return ob->ob_refcnt;
+}
+#define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob))
+
+
+static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) {
+    return ob->ob_size;
+}
+#define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob))
 
-#define Py_REFCNT(ob)           (_PyObject_CAST(ob)->ob_refcnt)
-#define Py_SIZE(ob)             (_PyVarObject_CAST(ob)->ob_size)
 
 static inline PyTypeObject* _Py_TYPE(const PyObject *ob) {
     return ob->ob_type;
 }
 #define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob))
 
+
 static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) {
     return ob->ob_type == type;
 }
 #define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type)
 
+
 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)
 
+
 static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
     ob->ob_type = type;
 }
 #define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type)
 
+
 static inline void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) {
     ob->ob_size = size;
 }
diff --git a/Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst b/Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst
new file mode 100644
index 0000000000000..f8f675cebcac7
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-05-26-16-21-47.bpo-39573.depAgq.rst	
@@ -0,0 +1,5 @@
+Convert :c:func:`Py_REFCNT` and :c:func:`Py_SIZE` macros to static inline
+functions. They cannot be used as l-value anymore: use
+:c:func:`Py_SET_REFCNT` and :c:func:`Py_SET_SIZE` to set an object reference
+count and size. This change is backward incompatible on purpose, to prepare
+the C API for an opaque :c:type:`PyObject` structure.
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index fb1b82cd6a6ec..4c3ddc3ac2457 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -2525,14 +2525,14 @@ array_buffer_getbuf(arrayobject *self, Py_buffer *view, int flags)
     Py_INCREF(self);
     if (view->buf == NULL)
         view->buf = (void *)emptybuf;
-    view->len = (Py_SIZE(self)) * self->ob_descr->itemsize;
+    view->len = Py_SIZE(self) * self->ob_descr->itemsize;
     view->readonly = 0;
     view->ndim = 1;
     view->itemsize = self->ob_descr->itemsize;
     view->suboffsets = NULL;
     view->shape = NULL;
     if ((flags & PyBUF_ND)==PyBUF_ND) {
-        view->shape = &((Py_SIZE(self)));
+        view->shape = &((PyVarObject*)self)->ob_size;
     }
     view->strides = NULL;
     if ((flags & PyBUF_STRIDES)==PyBUF_STRIDES)
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index e4c0c91cfe819..43706c22b9291 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -82,7 +82,7 @@ tuple_alloc(Py_ssize_t size)
         numfree[size]--;
         /* Inline PyObject_InitVar */
 #ifdef Py_TRACE_REFS
-        Py_SIZE(op) = size;
+        Py_SET_SIZE(op, size);
         Py_SET_TYPE(op, &PyTuple_Type);
 #endif
         _Py_NewReference((PyObject *)op);



More information about the Python-checkins mailing list