From 04fc4f2a46b2fd083639deb872c3a3037fdb47d6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 16 Jun 2020 01:28:07 +0200 Subject: [PATCH] bpo-40989: PyObject_INIT() becomes an alias to PyObject_Init() (GH-20901) The PyObject_INIT() and PyObject_INIT_VAR() macros become aliases to, respectively, PyObject_Init() and PyObject_InitVar() functions. Rename _PyObject_INIT() and _PyObject_INIT_VAR() static inline functions to, respectively, _PyObject_Init() and _PyObject_InitVar(), and move them to pycore_object.h. Remove their return value: their return type becomes void. The _datetime module is now built with the Py_BUILD_CORE_MODULE macro defined. Remove an outdated comment on _Py_tracemalloc_config. --- Include/cpython/objimpl.h | 39 ++----------------- Include/internal/pycore_object.h | 37 +++++++++++++++--- Include/internal/pycore_pymem.h | 3 -- Include/objimpl.h | 22 ++++------- .../2020-06-15-23-17-51.bpo-40989.tlzG3r.rst | 3 ++ Modules/_datetimemodule.c | 31 +++++++-------- Modules/gcmodule.c | 12 ++++-- Objects/bytesobject.c | 15 ++++--- Objects/complexobject.c | 11 +++--- Objects/floatobject.c | 5 ++- Objects/longobject.c | 4 +- Objects/object.c | 16 ++++---- Objects/tupleobject.c | 2 +- Objects/typeobject.c | 4 +- Objects/unicodeobject.c | 13 ++++--- PC/winreg.c | 10 ++--- setup.py | 3 +- 17 files changed, 113 insertions(+), 117 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-06-15-23-17-51.bpo-40989.tlzG3r.rst diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h index ca4009bcdb4..15999a239f7 100644 --- a/Include/cpython/objimpl.h +++ b/Include/cpython/objimpl.h @@ -37,8 +37,9 @@ PyObject *op; op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct)); - if (op == NULL) - return PyErr_NoMemory(); + if (op == NULL) { + return PyErr_NoMemory(); + } PyObject_Init(op, &YourTypeStruct); @@ -51,40 +52,6 @@ the 1st step is performed automatically for you, so in a C++ class constructor you would start directly with PyObject_Init/InitVar. */ - -/* Inline functions trading binary compatibility for speed: - PyObject_INIT() is the fast version of PyObject_Init(), and - PyObject_INIT_VAR() is the fast version of PyObject_InitVar(). - - These inline functions must not be called with op=NULL. */ -static inline PyObject* -_PyObject_INIT(PyObject *op, PyTypeObject *typeobj) -{ - assert(op != NULL); - Py_SET_TYPE(op, typeobj); - if (PyType_GetFlags(typeobj) & Py_TPFLAGS_HEAPTYPE) { - Py_INCREF(typeobj); - } - _Py_NewReference(op); - return op; -} - -#define PyObject_INIT(op, typeobj) \ - _PyObject_INIT(_PyObject_CAST(op), (typeobj)) - -static inline PyVarObject* -_PyObject_INIT_VAR(PyVarObject *op, PyTypeObject *typeobj, Py_ssize_t size) -{ - assert(op != NULL); - Py_SET_SIZE(op, size); - PyObject_INIT((PyObject *)op, typeobj); - return op; -} - -#define PyObject_INIT_VAR(op, typeobj, size) \ - _PyObject_INIT_VAR(_PyVarObject_CAST(op), (typeobj), (size)) - - /* This function returns the number of allocated memory blocks, regardless of size */ PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void); diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 32e86d06db5..14444a70ceb 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -15,6 +15,37 @@ extern "C" { PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type); PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content); +// Fast inlined version of PyType_HasFeature() +static inline int +_PyType_HasFeature(PyTypeObject *type, unsigned long feature) { + return ((type->tp_flags & feature) != 0); +} + +/* Inline functions trading binary compatibility for speed: + _PyObject_Init() is the fast version of PyObject_Init(), and + _PyObject_InitVar() is the fast version of PyObject_InitVar(). + + These inline functions must not be called with op=NULL. */ +static inline void +_PyObject_Init(PyObject *op, PyTypeObject *typeobj) +{ + assert(op != NULL); + Py_SET_TYPE(op, typeobj); + if (_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE)) { + Py_INCREF(typeobj); + } + _Py_NewReference(op); +} + +static inline void +_PyObject_InitVar(PyVarObject *op, PyTypeObject *typeobj, Py_ssize_t size) +{ + assert(op != NULL); + Py_SET_SIZE(op, size); + _PyObject_Init((PyObject *)op, typeobj); +} + + /* Tell the GC to track this object. * * NB: While the object is tracked by the collector, it must be safe to call the @@ -96,12 +127,6 @@ _PyObject_GET_WEAKREFS_LISTPTR(PyObject *op) return (PyObject **)((char *)op + offset); } -// Fast inlined version of PyType_HasFeature() -static inline int -_PyType_HasFeature(PyTypeObject *type, unsigned long feature) { - return ((type->tp_flags & feature) != 0); -} - // Fast inlined version of PyObject_IS_GC() static inline int _PyObject_IS_GC(PyObject *obj) diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h index 3d925e2250d..e4e35c16ce8 100644 --- a/Include/internal/pycore_pymem.h +++ b/Include/internal/pycore_pymem.h @@ -69,9 +69,6 @@ PyAPI_FUNC(int) _PyMem_GetAllocatorName( PYMEM_ALLOCATOR_NOT_SET does nothing. */ PyAPI_FUNC(int) _PyMem_SetupAllocators(PyMemAllocatorName allocator); -/* bpo-35053: Expose _Py_tracemalloc_config for _Py_NewReference() - which access directly _Py_tracemalloc_config.tracing for best - performances. */ struct _PyTraceMalloc_Config { /* Module initialized? Variable protected by the GIL */ diff --git a/Include/objimpl.h b/Include/objimpl.h index 030d7eee297..af537175bfe 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -118,7 +118,14 @@ PyAPI_FUNC(void) PyObject_Free(void *ptr); /* Functions */ PyAPI_FUNC(PyObject *) PyObject_Init(PyObject *, PyTypeObject *); PyAPI_FUNC(PyVarObject *) PyObject_InitVar(PyVarObject *, - PyTypeObject *, Py_ssize_t); + PyTypeObject *, Py_ssize_t); + +#define PyObject_INIT(op, typeobj) \ + PyObject_Init(_PyObject_CAST(op), (typeobj)) +#define PyObject_INIT_VAR(op, typeobj, size) \ + PyObject_InitVar(_PyVarObject_CAST(op), (typeobj), (size)) + + PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *); PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t); @@ -136,19 +143,6 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t); #define PyObject_NEW_VAR(type, typeobj, n) PyObject_NewVar(type, typeobj, n) -#ifdef Py_LIMITED_API -/* Define PyObject_INIT() and PyObject_INIT_VAR() as aliases to PyObject_Init() - and PyObject_InitVar() in the limited C API for compatibility with the - CPython C API. */ -# define PyObject_INIT(op, typeobj) \ - PyObject_Init(_PyObject_CAST(op), (typeobj)) -# define PyObject_INIT_VAR(op, typeobj, size) \ - PyObject_InitVar(_PyVarObject_CAST(op), (typeobj), (size)) -#else -/* PyObject_INIT() and PyObject_INIT_VAR() are defined in cpython/objimpl.h */ -#endif - - /* * Garbage Collection Support * ========================== diff --git a/Misc/NEWS.d/next/C API/2020-06-15-23-17-51.bpo-40989.tlzG3r.rst b/Misc/NEWS.d/next/C API/2020-06-15-23-17-51.bpo-40989.tlzG3r.rst new file mode 100644 index 00000000000..1be473d1427 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-06-15-23-17-51.bpo-40989.tlzG3r.rst @@ -0,0 +1,3 @@ +The :c:func:`PyObject_INIT` and :c:func:`PyObject_INIT_VAR` macros become +aliases to, respectively, :c:func:`PyObject_Init` and +:c:func:`PyObject_InitVar` functions. diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index acdde83dc84..74a54e74ae0 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -8,6 +8,7 @@ #define _PY_DATETIME_IMPL #include "Python.h" +#include "pycore_object.h" // _PyObject_Init() #include "datetime.h" #include "structmember.h" // PyMemberDef @@ -638,30 +639,24 @@ normalize_datetime(int *year, int *month, int *day, static PyObject * time_alloc(PyTypeObject *type, Py_ssize_t aware) { - PyObject *self; - - self = (PyObject *) - PyObject_MALLOC(aware ? - sizeof(PyDateTime_Time) : - sizeof(_PyDateTime_BaseTime)); - if (self == NULL) - return (PyObject *)PyErr_NoMemory(); - (void)PyObject_INIT(self, type); + size_t size = aware ? sizeof(PyDateTime_Time) : sizeof(_PyDateTime_BaseTime); + PyObject *self = (PyObject *)PyObject_Malloc(size); + if (self == NULL) { + return PyErr_NoMemory(); + } + _PyObject_Init(self, type); return self; } static PyObject * datetime_alloc(PyTypeObject *type, Py_ssize_t aware) { - PyObject *self; - - self = (PyObject *) - PyObject_MALLOC(aware ? - sizeof(PyDateTime_DateTime) : - sizeof(_PyDateTime_BaseDateTime)); - if (self == NULL) - return (PyObject *)PyErr_NoMemory(); - (void)PyObject_INIT(self, type); + size_t size = aware ? sizeof(PyDateTime_DateTime) : sizeof(_PyDateTime_BaseDateTime); + PyObject *self = (PyObject *)PyObject_Malloc(size); + if (self == NULL) { + return PyErr_NoMemory(); + } + _PyObject_Init(self, type); return self; } diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 444db7b03b4..110a48d8cd7 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -2263,8 +2263,10 @@ PyObject * _PyObject_GC_New(PyTypeObject *tp) { PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); - if (op != NULL) - op = PyObject_INIT(op, tp); + if (op == NULL) { + return NULL; + } + _PyObject_Init(op, tp); return op; } @@ -2280,8 +2282,10 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) } size = _PyObject_VAR_SIZE(tp, nitems); op = (PyVarObject *) _PyObject_GC_Malloc(size); - if (op != NULL) - op = PyObject_INIT_VAR(op, tp, nitems); + if (op == NULL) { + return NULL; + } + _PyObject_InitVar(op, tp, nitems); return op; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index b79c2460409..d3972142863 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -79,9 +79,10 @@ _PyBytes_FromSize(Py_ssize_t size, int use_calloc) op = (PyBytesObject *)PyObject_Calloc(1, PyBytesObject_SIZE + size); else op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + size); - if (op == NULL) + if (op == NULL) { return PyErr_NoMemory(); - (void)PyObject_INIT_VAR(op, &PyBytes_Type, size); + } + _PyObject_InitVar((PyVarObject*)op, &PyBytes_Type, size); op->ob_shash = -1; if (!use_calloc) op->ob_sval[size] = '\0'; @@ -148,9 +149,10 @@ PyBytes_FromString(const char *str) /* Inline PyObject_NewVar */ op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size); - if (op == NULL) + if (op == NULL) { return PyErr_NoMemory(); - (void)PyObject_INIT_VAR(op, &PyBytes_Type, size); + } + _PyObject_InitVar((PyVarObject*)op, &PyBytes_Type, size); op->ob_shash = -1; memcpy(op->ob_sval, str, size+1); /* share short strings */ @@ -1435,9 +1437,10 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n) return NULL; } op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + nbytes); - if (op == NULL) + if (op == NULL) { return PyErr_NoMemory(); - (void)PyObject_INIT_VAR(op, &PyBytes_Type, size); + } + _PyObject_InitVar((PyVarObject*)op, &PyBytes_Type, size); op->ob_shash = -1; op->ob_sval[size] = '\0'; if (Py_SIZE(a) == 1 && n > 0) { diff --git a/Objects/complexobject.c b/Objects/complexobject.c index a49037783be..d983a30901d 100644 --- a/Objects/complexobject.c +++ b/Objects/complexobject.c @@ -6,8 +6,10 @@ /* Submitted by Jim Hugunin */ #include "Python.h" +#include "pycore_object.h" // _PyObject_Init() #include "structmember.h" // PyMemberDef + /*[clinic input] class complex "PyComplexObject *" "&PyComplex_Type" [clinic start generated code]*/ @@ -229,13 +231,12 @@ complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval) PyObject * PyComplex_FromCComplex(Py_complex cval) { - PyComplexObject *op; - /* Inline PyObject_New */ - op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject)); - if (op == NULL) + PyComplexObject *op = PyObject_MALLOC(sizeof(PyComplexObject)); + if (op == NULL) { return PyErr_NoMemory(); - (void)PyObject_INIT(op, &PyComplex_Type); + } + _PyObject_Init((PyObject*)op, &PyComplex_Type); op->cval = cval; return (PyObject *) op; } diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 65625fe88ca..7ffd7eebe5a 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -4,8 +4,9 @@ for any kind of float exception without losing portability. */ #include "Python.h" -#include "pycore_dtoa.h" +#include "pycore_dtoa.h" // _Py_dg_dtoa() #include "pycore_interp.h" // _PyInterpreterState.float_state +#include "pycore_object.h" // _PyObject_Init() #include "pycore_pystate.h" // _PyInterpreterState_GET() #include @@ -129,7 +130,7 @@ PyFloat_FromDouble(double fval) return PyErr_NoMemory(); } } - (void)PyObject_INIT(op, &PyFloat_Type); + _PyObject_Init((PyObject*)op, &PyFloat_Type); op->ob_fval = fval; return (PyObject *) op; } diff --git a/Objects/longobject.c b/Objects/longobject.c index d92a9c56a72..d00a7a048dd 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -5,6 +5,7 @@ #include "Python.h" #include "pycore_bitutils.h" // _Py_popcount32() #include "pycore_interp.h" // _PY_NSMALLPOSINTS +#include "pycore_object.h" // _PyObject_InitVar() #include "pycore_pystate.h" // _Py_IsMainInterpreter() #include "longintrepr.h" @@ -146,7 +147,8 @@ _PyLong_New(Py_ssize_t size) PyErr_NoMemory(); return NULL; } - return (PyLongObject*)PyObject_INIT_VAR(result, &PyLong_Type, size); + _PyObject_InitVar((PyVarObject*)result, &PyLong_Type, size); + return result; } PyObject * diff --git a/Objects/object.c b/Objects/object.c index 0ab5de28499..4481fc91e1d 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -139,23 +139,23 @@ Py_DecRef(PyObject *o) PyObject * PyObject_Init(PyObject *op, PyTypeObject *tp) { - /* Any changes should be reflected in PyObject_INIT() macro */ if (op == NULL) { return PyErr_NoMemory(); } - return PyObject_INIT(op, tp); + _PyObject_Init(op, tp); + return op; } PyVarObject * PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size) { - /* Any changes should be reflected in PyObject_INIT_VAR() macro */ if (op == NULL) { return (PyVarObject *) PyErr_NoMemory(); } - return PyObject_INIT_VAR(op, tp, size); + _PyObject_InitVar(op, tp, size); + return op; } PyObject * @@ -165,7 +165,7 @@ _PyObject_New(PyTypeObject *tp) if (op == NULL) { return PyErr_NoMemory(); } - PyObject_INIT(op, tp); + _PyObject_Init(op, tp); return op; } @@ -175,9 +175,11 @@ _PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems) PyVarObject *op; const size_t size = _PyObject_VAR_SIZE(tp, nitems); op = (PyVarObject *) PyObject_MALLOC(size); - if (op == NULL) + if (op == NULL) { return (PyVarObject *)PyErr_NoMemory(); - return PyObject_INIT_VAR(op, tp, nitems); + } + _PyObject_InitVar(op, tp, nitems); + return op; } void diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 8bfa0894a79..2ff4c48111f 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -62,7 +62,7 @@ tuple_alloc(struct _Py_tuple_state *state, Py_ssize_t size) assert(size != 0); state->free_list[size] = (PyTupleObject *) op->ob_item[0]; state->numfree[size]--; - /* Inline PyObject_InitVar */ + /* Inlined _PyObject_InitVar() without _PyType_HasFeature() test */ #ifdef Py_TRACE_REFS Py_SET_SIZE(op, size); Py_SET_TYPE(op, &PyTuple_Type); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c8f0d2ee45f..f0e349ecd2b 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1060,10 +1060,10 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems) memset(obj, '\0', size); if (type->tp_itemsize == 0) { - (void)PyObject_INIT(obj, type); + _PyObject_Init(obj, type); } else { - (void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems); + _PyObject_InitVar((PyVarObject *)obj, type, nitems); } if (_PyType_IS_GC(type)) { diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 7ab0c882db0..c75eb077e0c 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1435,11 +1435,10 @@ PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar) * it's data buffer. */ obj = (PyObject *) PyObject_MALLOC(struct_size + (size + 1) * char_size); - if (obj == NULL) + if (obj == NULL) { return PyErr_NoMemory(); - obj = PyObject_INIT(obj, &PyUnicode_Type); - if (obj == NULL) - return NULL; + } + _PyObject_Init(obj, &PyUnicode_Type); unicode = (PyCompactUnicodeObject *)obj; if (is_ascii) @@ -8392,9 +8391,11 @@ PyUnicode_BuildEncodingMap(PyObject* string) /* Create a three-level trie */ result = PyObject_MALLOC(sizeof(struct encoding_map) + 16*count2 + 128*count3 - 1); - if (!result) + if (!result) { return PyErr_NoMemory(); - PyObject_Init(result, &EncodingMapType); + } + + _PyObject_Init(result, &EncodingMapType); mresult = (struct encoding_map*)result; mresult->count2 = count2; mresult->count3 = count3; diff --git a/PC/winreg.c b/PC/winreg.c index 1305b7030fa..7c3b2f4be85 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -14,6 +14,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pycore_object.h" // _PyObject_Init() #include "structmember.h" // PyMemberDef #include @@ -457,13 +458,12 @@ clinic_HKEY_converter(PyObject *ob, void *p) PyObject * PyHKEY_FromHKEY(HKEY h) { - PyHKEYObject *op; - /* Inline PyObject_New */ - op = (PyHKEYObject *) PyObject_MALLOC(sizeof(PyHKEYObject)); - if (op == NULL) + PyHKEYObject *op = (PyHKEYObject *) PyObject_MALLOC(sizeof(PyHKEYObject)); + if (op == NULL) { return PyErr_NoMemory(); - PyObject_INIT(op, &PyHKEY_Type); + } + _PyObject_Init(op, &PyHKEY_Type); op->hkey = h; return (PyObject *)op; } diff --git a/setup.py b/setup.py index ef2faf613be..b220f5279ca 100644 --- a/setup.py +++ b/setup.py @@ -853,7 +853,8 @@ class PyBuildExt(build_ext): # libm is needed by delta_new() that uses round() and by accum() that # uses modf(). self.add(Extension('_datetime', ['_datetimemodule.c'], - libraries=['m'])) + libraries=['m'], + extra_compile_args=['-DPy_BUILD_CORE_MODULE'])) # zoneinfo module self.add(Extension('_zoneinfo', ['_zoneinfo.c'])), # random number generator implemented in C