bpo-40170: PyObject_NEW() becomes an alias to PyObject_New() (GH-19379)
The PyObject_NEW() macro becomes an alias to the PyObject_New() macro, and the PyObject_NEW_VAR() macro becomes an alias to the PyObject_NewVar() macro, to hide implementation details. They no longer access directly the PyTypeObject.tp_basicsize member. Exclude _PyObject_SIZE() and _PyObject_VAR_SIZE() macros from the limited C API. Replace PyObject_NEW() with PyObject_New() and replace PyObject_NEW_VAR() with PyObject_NewVar().
This commit is contained in:
parent
f9dd51e7db
commit
9205520d8c
|
@ -6,6 +6,56 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
|
||||
|
||||
/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a
|
||||
vrbl-size object with nitems items, exclusive of gc overhead (if any). The
|
||||
value is rounded up to the closest multiple of sizeof(void *), in order to
|
||||
ensure that pointer fields at the end of the object are correctly aligned
|
||||
for the platform (this is of special importance for subclasses of, e.g.,
|
||||
str or int, so that pointers can be stored after the embedded data).
|
||||
|
||||
Note that there's no memory wastage in doing this, as malloc has to
|
||||
return (at worst) pointer-aligned memory anyway.
|
||||
*/
|
||||
#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0
|
||||
# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2"
|
||||
#endif
|
||||
|
||||
#define _PyObject_VAR_SIZE(typeobj, nitems) \
|
||||
_Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \
|
||||
(nitems)*(typeobj)->tp_itemsize, \
|
||||
SIZEOF_VOID_P)
|
||||
|
||||
|
||||
/* This example code implements an object constructor with a custom
|
||||
allocator, where PyObject_New is inlined, and shows the important
|
||||
distinction between two steps (at least):
|
||||
1) the actual allocation of the object storage;
|
||||
2) the initialization of the Python specific fields
|
||||
in this storage with PyObject_{Init, InitVar}.
|
||||
|
||||
PyObject *
|
||||
YourObject_New(...)
|
||||
{
|
||||
PyObject *op;
|
||||
|
||||
op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct));
|
||||
if (op == NULL)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
PyObject_Init(op, &YourTypeStruct);
|
||||
|
||||
op->ob_field = value;
|
||||
...
|
||||
return op;
|
||||
}
|
||||
|
||||
Note that in C++, the use of the new operator usually implies that
|
||||
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().
|
||||
|
|
|
@ -122,12 +122,18 @@ PyAPI_FUNC(PyVarObject *) PyObject_InitVar(PyVarObject *,
|
|||
PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
|
||||
PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
|
||||
|
||||
#define PyObject_New(type, typeobj) \
|
||||
( (type *) _PyObject_New(typeobj) )
|
||||
#define PyObject_New(type, typeobj) ((type *)_PyObject_New(typeobj))
|
||||
|
||||
// Alias to PyObject_New(). In Python 3.8, PyObject_NEW() called directly
|
||||
// PyObject_MALLOC() with _PyObject_SIZE().
|
||||
#define PyObject_NEW(type, typeobj) PyObject_New(type, typeobj)
|
||||
|
||||
#define PyObject_NewVar(type, typeobj, n) \
|
||||
( (type *) _PyObject_NewVar((typeobj), (n)) )
|
||||
|
||||
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
|
||||
// Alias to PyObject_New(). In Python 3.8, PyObject_NEW() called directly
|
||||
// PyObject_MALLOC() with _PyObject_VAR_SIZE().
|
||||
#define PyObject_NEW_VAR(type, typeobj, n) PyObject_NewVar(type, typeobj, n)
|
||||
|
||||
|
||||
#ifdef Py_LIMITED_API
|
||||
|
@ -143,64 +149,6 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
|
|||
#endif
|
||||
|
||||
|
||||
/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a
|
||||
vrbl-size object with nitems items, exclusive of gc overhead (if any). The
|
||||
value is rounded up to the closest multiple of sizeof(void *), in order to
|
||||
ensure that pointer fields at the end of the object are correctly aligned
|
||||
for the platform (this is of special importance for subclasses of, e.g.,
|
||||
str or int, so that pointers can be stored after the embedded data).
|
||||
|
||||
Note that there's no memory wastage in doing this, as malloc has to
|
||||
return (at worst) pointer-aligned memory anyway.
|
||||
*/
|
||||
#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0
|
||||
# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2"
|
||||
#endif
|
||||
|
||||
#define _PyObject_VAR_SIZE(typeobj, nitems) \
|
||||
_Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \
|
||||
(nitems)*(typeobj)->tp_itemsize, \
|
||||
SIZEOF_VOID_P)
|
||||
|
||||
#define PyObject_NEW(type, typeobj) \
|
||||
( (type *) PyObject_Init( \
|
||||
(PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) )
|
||||
|
||||
#define PyObject_NEW_VAR(type, typeobj, n) \
|
||||
( (type *) PyObject_InitVar( \
|
||||
(PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE((typeobj),(n)) ),\
|
||||
(typeobj), (n)) )
|
||||
|
||||
/* This example code implements an object constructor with a custom
|
||||
allocator, where PyObject_New is inlined, and shows the important
|
||||
distinction between two steps (at least):
|
||||
1) the actual allocation of the object storage;
|
||||
2) the initialization of the Python specific fields
|
||||
in this storage with PyObject_{Init, InitVar}.
|
||||
|
||||
PyObject *
|
||||
YourObject_New(...)
|
||||
{
|
||||
PyObject *op;
|
||||
|
||||
op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct));
|
||||
if (op == NULL)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
PyObject_Init(op, &YourTypeStruct);
|
||||
|
||||
op->ob_field = value;
|
||||
...
|
||||
return op;
|
||||
}
|
||||
|
||||
Note that in C++, the use of the new operator usually implies that
|
||||
the 1st step is performed automatically for you, so in a C++ class
|
||||
constructor you would start directly with PyObject_Init/InitVar
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Garbage Collection Support
|
||||
* ==========================
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
The :c:func:`PyObject_NEW` macro becomes an alias to the :c:func:`PyObject_New`
|
||||
macro, and the :c:func:`PyObject_NEW_VAR` macro becomes an alias to the
|
||||
:c:func:`PyObject_NewVar` macro, to hide implementation details. They no longer
|
||||
access directly the :c:member:`PyTypeObject.tp_basicsize` member.
|
|
@ -239,7 +239,7 @@ PyCursesPanel_New(PANEL *pan, PyCursesWindowObject *wo)
|
|||
{
|
||||
PyCursesPanelObject *po;
|
||||
|
||||
po = PyObject_NEW(PyCursesPanelObject,
|
||||
po = PyObject_New(PyCursesPanelObject,
|
||||
(PyTypeObject *)(_curses_panelstate_global)->PyCursesPanel_Type);
|
||||
if (po == NULL) return NULL;
|
||||
po->pan = pan;
|
||||
|
|
|
@ -547,7 +547,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding)
|
|||
encoding = "utf-8";
|
||||
}
|
||||
|
||||
wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type);
|
||||
wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type);
|
||||
if (wo == NULL) return NULL;
|
||||
wo->win = win;
|
||||
wo->encoding = _PyMem_Strdup(encoding);
|
||||
|
|
|
@ -1338,7 +1338,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags,
|
|||
|
||||
n = PyList_GET_SIZE(code);
|
||||
/* coverity[ampersand_in_size] */
|
||||
self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n);
|
||||
self = PyObject_NewVar(PatternObject, &Pattern_Type, n);
|
||||
if (!self)
|
||||
return NULL;
|
||||
self->weakreflist = NULL;
|
||||
|
@ -2327,8 +2327,8 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status)
|
|||
|
||||
/* create match object (with room for extra group marks) */
|
||||
/* coverity[ampersand_in_size] */
|
||||
match = PyObject_NEW_VAR(MatchObject, &Match_Type,
|
||||
2*(pattern->groups+1));
|
||||
match = PyObject_NewVar(MatchObject, &Match_Type,
|
||||
2*(pattern->groups+1));
|
||||
if (!match)
|
||||
return NULL;
|
||||
|
||||
|
@ -2468,7 +2468,7 @@ pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_
|
|||
ScannerObject* scanner;
|
||||
|
||||
/* create scanner object */
|
||||
scanner = PyObject_NEW(ScannerObject, &Scanner_Type);
|
||||
scanner = PyObject_New(ScannerObject, &Scanner_Type);
|
||||
if (!scanner)
|
||||
return NULL;
|
||||
scanner->pattern = NULL;
|
||||
|
|
|
@ -50,7 +50,7 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
|
||||
capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
|
||||
if (capsule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
|
|||
cell2arg = NULL;
|
||||
}
|
||||
}
|
||||
co = PyObject_NEW(PyCodeObject, &PyCode_Type);
|
||||
co = PyObject_New(PyCodeObject, &PyCode_Type);
|
||||
if (co == NULL) {
|
||||
if (cell2arg)
|
||||
PyMem_FREE(cell2arg);
|
||||
|
|
|
@ -161,11 +161,12 @@ PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
|
|||
PyObject *
|
||||
_PyObject_New(PyTypeObject *tp)
|
||||
{
|
||||
PyObject *op;
|
||||
op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
|
||||
if (op == NULL)
|
||||
PyObject *op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
|
||||
if (op == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
return PyObject_INIT(op, tp);
|
||||
}
|
||||
PyObject_INIT(op, tp);
|
||||
return op;
|
||||
}
|
||||
|
||||
PyVarObject *
|
||||
|
|
|
@ -531,7 +531,7 @@ static PyTypeObject record_Type = {
|
|||
static PyObject*
|
||||
record_new(MSIHANDLE h)
|
||||
{
|
||||
msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
|
||||
msiobj *result = PyObject_New(struct msiobj, &record_Type);
|
||||
|
||||
if (!result) {
|
||||
MsiCloseHandle(h);
|
||||
|
@ -882,7 +882,7 @@ msidb_openview(msiobj *msidb, PyObject *args)
|
|||
if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)
|
||||
return msierror(status);
|
||||
|
||||
result = PyObject_NEW(struct msiobj, &msiview_Type);
|
||||
result = PyObject_New(struct msiobj, &msiview_Type);
|
||||
if (!result) {
|
||||
MsiCloseHandle(hView);
|
||||
return NULL;
|
||||
|
@ -918,7 +918,7 @@ msidb_getsummaryinformation(msiobj *db, PyObject *args)
|
|||
if (status != ERROR_SUCCESS)
|
||||
return msierror(status);
|
||||
|
||||
oresult = PyObject_NEW(struct msiobj, &summary_Type);
|
||||
oresult = PyObject_New(struct msiobj, &summary_Type);
|
||||
if (!oresult) {
|
||||
MsiCloseHandle(result);
|
||||
return NULL;
|
||||
|
@ -1013,7 +1013,7 @@ static PyObject* msiopendb(PyObject *obj, PyObject *args)
|
|||
if (status != ERROR_SUCCESS)
|
||||
return msierror(status);
|
||||
|
||||
result = PyObject_NEW(struct msiobj, &msidb_Type);
|
||||
result = PyObject_New(struct msiobj, &msidb_Type);
|
||||
if (!result) {
|
||||
MsiCloseHandle(h);
|
||||
return NULL;
|
||||
|
|
|
@ -390,7 +390,7 @@ PyTypeObject PyHKEY_Type =
|
|||
PyObject *
|
||||
PyHKEY_New(HKEY hInit)
|
||||
{
|
||||
PyHKEYObject *key = PyObject_NEW(PyHKEYObject, &PyHKEY_Type);
|
||||
PyHKEYObject *key = PyObject_New(PyHKEYObject, &PyHKEY_Type);
|
||||
if (key)
|
||||
key->hkey = hInit;
|
||||
return (PyObject *)key;
|
||||
|
|
Loading…
Reference in New Issue