summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-07 22:38:15 (GMT)
committerGitHub <noreply@github.com>2020-04-07 22:38:15 (GMT)
commit9205520d8c43488696d66cbdd9aefbb21871c508 (patch)
tree6c6d03828fddd763f261d89a9afef18b109c0d3d
parentf9dd51e7db27d04e0b716d41a2804d5acbf145d1 (diff)
downloadcpython-9205520d8c43488696d66cbdd9aefbb21871c508.zip
cpython-9205520d8c43488696d66cbdd9aefbb21871c508.tar.gz
cpython-9205520d8c43488696d66cbdd9aefbb21871c508.tar.bz2
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().
-rw-r--r--Include/cpython/objimpl.h50
-rw-r--r--Include/objimpl.h70
-rw-r--r--Misc/NEWS.d/next/C API/2020-04-05-00-37-34.bpo-40170.Seuh3D.rst4
-rw-r--r--Modules/_curses_panel.c2
-rw-r--r--Modules/_cursesmodule.c2
-rw-r--r--Modules/_sre.c8
-rw-r--r--Objects/capsule.c2
-rw-r--r--Objects/codeobject.c2
-rw-r--r--Objects/object.c9
-rw-r--r--PC/_msi.c8
-rw-r--r--PC/winreg.c2
11 files changed, 81 insertions, 78 deletions
diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h
index 2f802e9..832622c 100644
--- a/Include/cpython/objimpl.h
+++ b/Include/cpython/objimpl.h
@@ -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().
diff --git a/Include/objimpl.h b/Include/objimpl.h
index 4591925..6e7549c 100644
--- a/Include/objimpl.h
+++ b/Include/objimpl.h
@@ -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
* ==========================
diff --git a/Misc/NEWS.d/next/C API/2020-04-05-00-37-34.bpo-40170.Seuh3D.rst b/Misc/NEWS.d/next/C API/2020-04-05-00-37-34.bpo-40170.Seuh3D.rst
new file mode 100644
index 0000000..2c31cca
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-04-05-00-37-34.bpo-40170.Seuh3D.rst
@@ -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.
diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
index 77a6a14..7ca91f6 100644
--- a/Modules/_curses_panel.c
+++ b/Modules/_curses_panel.c
@@ -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;
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 3d16af7..ca6a89f 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -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);
diff --git a/Modules/_sre.c b/Modules/_sre.c
index 52ed420..bee2e12 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -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;
diff --git a/Objects/capsule.c b/Objects/capsule.c
index 599893a..ed24cc1 100644
--- a/Objects/capsule.c
+++ b/Objects/capsule.c
@@ -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;
}
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index fd64393..1820d8c 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -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);
diff --git a/Objects/object.c b/Objects/object.c
index 05241e8..069afc0 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -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 *
diff --git a/PC/_msi.c b/PC/_msi.c
index accbe7a..6ed8724 100644
--- a/PC/_msi.c
+++ b/PC/_msi.c
@@ -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;
diff --git a/PC/winreg.c b/PC/winreg.c
index 5dff7de..ec2f607 100644
--- a/PC/winreg.c
+++ b/PC/winreg.c
@@ -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;