From ad86f1cf0948979115e70f0ef4904cf90c0f7b76 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 17 Sep 2021 14:23:27 +0200 Subject: [PATCH 1/2] bpo-45116: Use Py_ALWAYS_INLINE in object.h Use Py_ALWAYS_INLINE on all static inline functions of object.h: * Py_REFCNT(), Py_SET_REFCNT() * Py_TYPE(), Py_SET_TYPE() * Py_SIZE(), Py_SET_SIZE() * Py_IS_TYPE() * PyObject_TypeCheck() * Py_INCREF(), Py_XINCREF() * Py_DECREF(), Py_XDECREF() * Py_NewRef(), Py_XNewRef() * PyType_HasFeature() * PyType_Check(), PyType_CheckExact() These static inline functions are short, simple and were macros in older Python versions. --- Include/object.h | 59 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/Include/object.h b/Include/object.h index 490cbffd5f1074..1a663cec7b5611 100644 --- a/Include/object.h +++ b/Include/object.h @@ -127,26 +127,33 @@ PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y); #define Py_Is(x, y) ((x) == (y)) -static inline Py_ssize_t _Py_REFCNT(const PyObject *ob) { +static inline Py_ssize_t Py_ALWAYS_INLINE +_Py_REFCNT(const PyObject *ob) { return ob->ob_refcnt; } #define Py_REFCNT(ob) _Py_REFCNT(_PyObject_CAST_CONST(ob)) // bpo-39573: The Py_SET_TYPE() function must be used to set an object type. -static inline PyTypeObject* _Py_TYPE(const PyObject *ob) { +static inline PyTypeObject* Py_ALWAYS_INLINE +_Py_TYPE(const PyObject *ob) +{ return ob->ob_type; } #define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob)) // bpo-39573: The Py_SET_SIZE() function must be used to set an object size. -static inline Py_ssize_t _Py_SIZE(const PyVarObject *ob) { +static inline Py_ssize_t Py_ALWAYS_INLINE +_Py_SIZE(const PyVarObject *ob) +{ return ob->ob_size; } #define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob)) -static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { +static inline int Py_ALWAYS_INLINE +_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) +{ // bpo-44378: Don't use Py_TYPE() since Py_TYPE() requires a non-const // object. return ob->ob_type == type; @@ -154,19 +161,25 @@ static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *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) { +static inline void Py_ALWAYS_INLINE +_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) { +static inline void Py_ALWAYS_INLINE +_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) { +static inline void Py_ALWAYS_INLINE +_Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) +{ ob->ob_size = size; } #define Py_SET_SIZE(ob, size) _Py_SET_SIZE(_PyVarObject_CAST(ob), size) @@ -253,7 +266,9 @@ PyAPI_FUNC(PyObject *) PyType_GetQualName(PyTypeObject *); /* Generic type check */ PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *); -static inline int _PyObject_TypeCheck(PyObject *ob, PyTypeObject *type) { +static inline int Py_ALWAYS_INLINE +_PyObject_TypeCheck(PyObject *ob, PyTypeObject *type) +{ return Py_IS_TYPE(ob, type) || PyType_IsSubtype(Py_TYPE(ob), type); } #define PyObject_TypeCheck(ob, type) _PyObject_TypeCheck(_PyObject_CAST(ob), type) @@ -468,7 +483,8 @@ PyAPI_FUNC(void) Py_DecRef(PyObject *); PyAPI_FUNC(void) _Py_IncRef(PyObject *); PyAPI_FUNC(void) _Py_DecRef(PyObject *); -static inline void _Py_INCREF(PyObject *op) +static inline void Py_ALWAYS_INLINE +_Py_INCREF(PyObject *op) { #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 // Stable ABI for Python 3.10 built in debug mode. @@ -484,7 +500,8 @@ static inline void _Py_INCREF(PyObject *op) } #define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op)) -static inline void _Py_DECREF( +static inline void Py_ALWAYS_INLINE +_Py_DECREF( #if defined(Py_REF_DEBUG) && !(defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000) const char *filename, int lineno, #endif @@ -562,7 +579,8 @@ static inline void _Py_DECREF( } while (0) /* Function to use in case the object pointer can be NULL: */ -static inline void _Py_XINCREF(PyObject *op) +static inline void Py_ALWAYS_INLINE +_Py_XINCREF(PyObject *op) { if (op != NULL) { Py_INCREF(op); @@ -571,7 +589,8 @@ static inline void _Py_XINCREF(PyObject *op) #define Py_XINCREF(op) _Py_XINCREF(_PyObject_CAST(op)) -static inline void _Py_XDECREF(PyObject *op) +static inline void Py_ALWAYS_INLINE +_Py_XDECREF(PyObject *op) { if (op != NULL) { Py_DECREF(op); @@ -587,13 +606,15 @@ PyAPI_FUNC(PyObject*) Py_NewRef(PyObject *obj); // Similar to Py_NewRef(), but the object can be NULL. PyAPI_FUNC(PyObject*) Py_XNewRef(PyObject *obj); -static inline PyObject* _Py_NewRef(PyObject *obj) +static inline PyObject* Py_ALWAYS_INLINE +_Py_NewRef(PyObject *obj) { Py_INCREF(obj); return obj; } -static inline PyObject* _Py_XNewRef(PyObject *obj) +static inline PyObject* Py_ALWAYS_INLINE +_Py_XNewRef(PyObject *obj) { Py_XINCREF(obj); return obj; @@ -728,7 +749,7 @@ times. #endif -static inline int +static inline int Py_ALWAYS_INLINE PyType_HasFeature(PyTypeObject *type, unsigned long feature) { unsigned long flags; @@ -743,12 +764,16 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature) #define PyType_FastSubclass(type, flag) PyType_HasFeature(type, flag) -static inline int _PyType_Check(PyObject *op) { +static inline int Py_ALWAYS_INLINE +_PyType_Check(PyObject *op) +{ return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS); } #define PyType_Check(op) _PyType_Check(_PyObject_CAST(op)) -static inline int _PyType_CheckExact(PyObject *op) { +static inline int Py_ALWAYS_INLINE +_PyType_CheckExact(PyObject *op) +{ return Py_IS_TYPE(op, &PyType_Type); } #define PyType_CheckExact(op) _PyType_CheckExact(_PyObject_CAST(op)) From ae234ffea2d2c27ba927e446bdd032ada9c42953 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 19 Sep 2021 11:48:04 +0200 Subject: [PATCH 2/2] Fix build on Windows Py_ALWAYS_INLINE must be specified *before* the return type --- Include/object.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Include/object.h b/Include/object.h index 1a663cec7b5611..7e49901f0a9136 100644 --- a/Include/object.h +++ b/Include/object.h @@ -127,7 +127,7 @@ PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y); #define Py_Is(x, y) ((x) == (y)) -static inline Py_ssize_t Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE Py_ssize_t _Py_REFCNT(const PyObject *ob) { return ob->ob_refcnt; } @@ -135,7 +135,7 @@ _Py_REFCNT(const PyObject *ob) { // bpo-39573: The Py_SET_TYPE() function must be used to set an object type. -static inline PyTypeObject* Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE PyTypeObject* _Py_TYPE(const PyObject *ob) { return ob->ob_type; @@ -143,7 +143,7 @@ _Py_TYPE(const PyObject *ob) #define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST_CONST(ob)) // bpo-39573: The Py_SET_SIZE() function must be used to set an object size. -static inline Py_ssize_t Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE Py_ssize_t _Py_SIZE(const PyVarObject *ob) { return ob->ob_size; @@ -151,7 +151,7 @@ _Py_SIZE(const PyVarObject *ob) #define Py_SIZE(ob) _Py_SIZE(_PyVarObject_CAST_CONST(ob)) -static inline int Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { // bpo-44378: Don't use Py_TYPE() since Py_TYPE() requires a non-const @@ -161,7 +161,7 @@ _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) #define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_refcnt = refcnt; @@ -169,7 +169,7 @@ _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) #define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { ob->ob_type = type; @@ -177,7 +177,7 @@ _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) #define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { ob->ob_size = size; @@ -266,7 +266,7 @@ PyAPI_FUNC(PyObject *) PyType_GetQualName(PyTypeObject *); /* Generic type check */ PyAPI_FUNC(int) PyType_IsSubtype(PyTypeObject *, PyTypeObject *); -static inline int Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE int _PyObject_TypeCheck(PyObject *ob, PyTypeObject *type) { return Py_IS_TYPE(ob, type) || PyType_IsSubtype(Py_TYPE(ob), type); @@ -483,7 +483,7 @@ PyAPI_FUNC(void) Py_DecRef(PyObject *); PyAPI_FUNC(void) _Py_IncRef(PyObject *); PyAPI_FUNC(void) _Py_DecRef(PyObject *); -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_INCREF(PyObject *op) { #if defined(Py_REF_DEBUG) && defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000 @@ -500,7 +500,7 @@ _Py_INCREF(PyObject *op) } #define Py_INCREF(op) _Py_INCREF(_PyObject_CAST(op)) -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_DECREF( #if defined(Py_REF_DEBUG) && !(defined(Py_LIMITED_API) && Py_LIMITED_API+0 >= 0x030A0000) const char *filename, int lineno, @@ -579,7 +579,7 @@ _Py_DECREF( } while (0) /* Function to use in case the object pointer can be NULL: */ -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_XINCREF(PyObject *op) { if (op != NULL) { @@ -589,7 +589,7 @@ _Py_XINCREF(PyObject *op) #define Py_XINCREF(op) _Py_XINCREF(_PyObject_CAST(op)) -static inline void Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE void _Py_XDECREF(PyObject *op) { if (op != NULL) { @@ -606,14 +606,14 @@ PyAPI_FUNC(PyObject*) Py_NewRef(PyObject *obj); // Similar to Py_NewRef(), but the object can be NULL. PyAPI_FUNC(PyObject*) Py_XNewRef(PyObject *obj); -static inline PyObject* Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE PyObject* _Py_NewRef(PyObject *obj) { Py_INCREF(obj); return obj; } -static inline PyObject* Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE PyObject* _Py_XNewRef(PyObject *obj) { Py_XINCREF(obj); @@ -749,7 +749,7 @@ times. #endif -static inline int Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE int PyType_HasFeature(PyTypeObject *type, unsigned long feature) { unsigned long flags; @@ -764,14 +764,14 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature) #define PyType_FastSubclass(type, flag) PyType_HasFeature(type, flag) -static inline int Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE int _PyType_Check(PyObject *op) { return PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS); } #define PyType_Check(op) _PyType_Check(_PyObject_CAST(op)) -static inline int Py_ALWAYS_INLINE +static inline Py_ALWAYS_INLINE int _PyType_CheckExact(PyObject *op) { return Py_IS_TYPE(op, &PyType_Type);