Skip to content

Commit

Permalink
bpo-39573: Convert Py_REFCNT and Py_SIZE to functions (pythonGH-20429)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vstinner authored May 27, 2020
1 parent 20941de commit fe2978b
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 14 deletions.
19 changes: 10 additions & 9 deletions Doc/c-api/structures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
-------
19 changes: 17 additions & 2 deletions Include/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 2 additions & 2 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit fe2978b

Please sign in to comment.