Skip to content

Commit 9205520

Browse files
authored
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().
1 parent f9dd51e commit 9205520

File tree

11 files changed

+81
-78
lines changed

11 files changed

+81
-78
lines changed

Include/cpython/objimpl.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,56 @@
66
extern "C" {
77
#endif
88

9+
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
10+
11+
/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a
12+
vrbl-size object with nitems items, exclusive of gc overhead (if any). The
13+
value is rounded up to the closest multiple of sizeof(void *), in order to
14+
ensure that pointer fields at the end of the object are correctly aligned
15+
for the platform (this is of special importance for subclasses of, e.g.,
16+
str or int, so that pointers can be stored after the embedded data).
17+
18+
Note that there's no memory wastage in doing this, as malloc has to
19+
return (at worst) pointer-aligned memory anyway.
20+
*/
21+
#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0
22+
# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2"
23+
#endif
24+
25+
#define _PyObject_VAR_SIZE(typeobj, nitems) \
26+
_Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \
27+
(nitems)*(typeobj)->tp_itemsize, \
28+
SIZEOF_VOID_P)
29+
30+
31+
/* This example code implements an object constructor with a custom
32+
allocator, where PyObject_New is inlined, and shows the important
33+
distinction between two steps (at least):
34+
1) the actual allocation of the object storage;
35+
2) the initialization of the Python specific fields
36+
in this storage with PyObject_{Init, InitVar}.
37+
38+
PyObject *
39+
YourObject_New(...)
40+
{
41+
PyObject *op;
42+
43+
op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct));
44+
if (op == NULL)
45+
return PyErr_NoMemory();
46+
47+
PyObject_Init(op, &YourTypeStruct);
48+
49+
op->ob_field = value;
50+
...
51+
return op;
52+
}
53+
54+
Note that in C++, the use of the new operator usually implies that
55+
the 1st step is performed automatically for you, so in a C++ class
56+
constructor you would start directly with PyObject_Init/InitVar. */
57+
58+
959
/* Inline functions trading binary compatibility for speed:
1060
PyObject_INIT() is the fast version of PyObject_Init(), and
1161
PyObject_INIT_VAR() is the fast version of PyObject_InitVar().

Include/objimpl.h

Lines changed: 9 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,18 @@ PyAPI_FUNC(PyVarObject *) PyObject_InitVar(PyVarObject *,
122122
PyAPI_FUNC(PyObject *) _PyObject_New(PyTypeObject *);
123123
PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
124124

125-
#define PyObject_New(type, typeobj) \
126-
( (type *) _PyObject_New(typeobj) )
125+
#define PyObject_New(type, typeobj) ((type *)_PyObject_New(typeobj))
126+
127+
// Alias to PyObject_New(). In Python 3.8, PyObject_NEW() called directly
128+
// PyObject_MALLOC() with _PyObject_SIZE().
129+
#define PyObject_NEW(type, typeobj) PyObject_New(type, typeobj)
130+
127131
#define PyObject_NewVar(type, typeobj, n) \
128132
( (type *) _PyObject_NewVar((typeobj), (n)) )
129133

130-
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
134+
// Alias to PyObject_New(). In Python 3.8, PyObject_NEW() called directly
135+
// PyObject_MALLOC() with _PyObject_VAR_SIZE().
136+
#define PyObject_NEW_VAR(type, typeobj, n) PyObject_NewVar(type, typeobj, n)
131137

132138

133139
#ifdef Py_LIMITED_API
@@ -143,64 +149,6 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
143149
#endif
144150

145151

146-
/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a
147-
vrbl-size object with nitems items, exclusive of gc overhead (if any). The
148-
value is rounded up to the closest multiple of sizeof(void *), in order to
149-
ensure that pointer fields at the end of the object are correctly aligned
150-
for the platform (this is of special importance for subclasses of, e.g.,
151-
str or int, so that pointers can be stored after the embedded data).
152-
153-
Note that there's no memory wastage in doing this, as malloc has to
154-
return (at worst) pointer-aligned memory anyway.
155-
*/
156-
#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0
157-
# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2"
158-
#endif
159-
160-
#define _PyObject_VAR_SIZE(typeobj, nitems) \
161-
_Py_SIZE_ROUND_UP((typeobj)->tp_basicsize + \
162-
(nitems)*(typeobj)->tp_itemsize, \
163-
SIZEOF_VOID_P)
164-
165-
#define PyObject_NEW(type, typeobj) \
166-
( (type *) PyObject_Init( \
167-
(PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) )
168-
169-
#define PyObject_NEW_VAR(type, typeobj, n) \
170-
( (type *) PyObject_InitVar( \
171-
(PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE((typeobj),(n)) ),\
172-
(typeobj), (n)) )
173-
174-
/* This example code implements an object constructor with a custom
175-
allocator, where PyObject_New is inlined, and shows the important
176-
distinction between two steps (at least):
177-
1) the actual allocation of the object storage;
178-
2) the initialization of the Python specific fields
179-
in this storage with PyObject_{Init, InitVar}.
180-
181-
PyObject *
182-
YourObject_New(...)
183-
{
184-
PyObject *op;
185-
186-
op = (PyObject *) Your_Allocator(_PyObject_SIZE(YourTypeStruct));
187-
if (op == NULL)
188-
return PyErr_NoMemory();
189-
190-
PyObject_Init(op, &YourTypeStruct);
191-
192-
op->ob_field = value;
193-
...
194-
return op;
195-
}
196-
197-
Note that in C++, the use of the new operator usually implies that
198-
the 1st step is performed automatically for you, so in a C++ class
199-
constructor you would start directly with PyObject_Init/InitVar
200-
*/
201-
202-
203-
204152
/*
205153
* Garbage Collection Support
206154
* ==========================
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The :c:func:`PyObject_NEW` macro becomes an alias to the :c:func:`PyObject_New`
2+
macro, and the :c:func:`PyObject_NEW_VAR` macro becomes an alias to the
3+
:c:func:`PyObject_NewVar` macro, to hide implementation details. They no longer
4+
access directly the :c:member:`PyTypeObject.tp_basicsize` member.

Modules/_curses_panel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ PyCursesPanel_New(PANEL *pan, PyCursesWindowObject *wo)
239239
{
240240
PyCursesPanelObject *po;
241241

242-
po = PyObject_NEW(PyCursesPanelObject,
242+
po = PyObject_New(PyCursesPanelObject,
243243
(PyTypeObject *)(_curses_panelstate_global)->PyCursesPanel_Type);
244244
if (po == NULL) return NULL;
245245
po->pan = pan;

Modules/_cursesmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding)
547547
encoding = "utf-8";
548548
}
549549

550-
wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type);
550+
wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type);
551551
if (wo == NULL) return NULL;
552552
wo->win = win;
553553
wo->encoding = _PyMem_Strdup(encoding);

Modules/_sre.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ _sre_compile_impl(PyObject *module, PyObject *pattern, int flags,
13381338

13391339
n = PyList_GET_SIZE(code);
13401340
/* coverity[ampersand_in_size] */
1341-
self = PyObject_NEW_VAR(PatternObject, &Pattern_Type, n);
1341+
self = PyObject_NewVar(PatternObject, &Pattern_Type, n);
13421342
if (!self)
13431343
return NULL;
13441344
self->weakreflist = NULL;
@@ -2327,8 +2327,8 @@ pattern_new_match(PatternObject* pattern, SRE_STATE* state, Py_ssize_t status)
23272327

23282328
/* create match object (with room for extra group marks) */
23292329
/* coverity[ampersand_in_size] */
2330-
match = PyObject_NEW_VAR(MatchObject, &Match_Type,
2331-
2*(pattern->groups+1));
2330+
match = PyObject_NewVar(MatchObject, &Match_Type,
2331+
2*(pattern->groups+1));
23322332
if (!match)
23332333
return NULL;
23342334

@@ -2468,7 +2468,7 @@ pattern_scanner(PatternObject *self, PyObject *string, Py_ssize_t pos, Py_ssize_
24682468
ScannerObject* scanner;
24692469

24702470
/* create scanner object */
2471-
scanner = PyObject_NEW(ScannerObject, &Scanner_Type);
2471+
scanner = PyObject_New(ScannerObject, &Scanner_Type);
24722472
if (!scanner)
24732473
return NULL;
24742474
scanner->pattern = NULL;

Objects/capsule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
5050
return NULL;
5151
}
5252

53-
capsule = PyObject_NEW(PyCapsule, &PyCapsule_Type);
53+
capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
5454
if (capsule == NULL) {
5555
return NULL;
5656
}

Objects/codeobject.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
219219
cell2arg = NULL;
220220
}
221221
}
222-
co = PyObject_NEW(PyCodeObject, &PyCode_Type);
222+
co = PyObject_New(PyCodeObject, &PyCode_Type);
223223
if (co == NULL) {
224224
if (cell2arg)
225225
PyMem_FREE(cell2arg);

Objects/object.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,12 @@ PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
161161
PyObject *
162162
_PyObject_New(PyTypeObject *tp)
163163
{
164-
PyObject *op;
165-
op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
166-
if (op == NULL)
164+
PyObject *op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
165+
if (op == NULL) {
167166
return PyErr_NoMemory();
168-
return PyObject_INIT(op, tp);
167+
}
168+
PyObject_INIT(op, tp);
169+
return op;
169170
}
170171

171172
PyVarObject *

PC/_msi.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ static PyTypeObject record_Type = {
531531
static PyObject*
532532
record_new(MSIHANDLE h)
533533
{
534-
msiobj *result = PyObject_NEW(struct msiobj, &record_Type);
534+
msiobj *result = PyObject_New(struct msiobj, &record_Type);
535535

536536
if (!result) {
537537
MsiCloseHandle(h);
@@ -882,7 +882,7 @@ msidb_openview(msiobj *msidb, PyObject *args)
882882
if ((status = MsiDatabaseOpenView(msidb->h, sql, &hView)) != ERROR_SUCCESS)
883883
return msierror(status);
884884

885-
result = PyObject_NEW(struct msiobj, &msiview_Type);
885+
result = PyObject_New(struct msiobj, &msiview_Type);
886886
if (!result) {
887887
MsiCloseHandle(hView);
888888
return NULL;
@@ -918,7 +918,7 @@ msidb_getsummaryinformation(msiobj *db, PyObject *args)
918918
if (status != ERROR_SUCCESS)
919919
return msierror(status);
920920

921-
oresult = PyObject_NEW(struct msiobj, &summary_Type);
921+
oresult = PyObject_New(struct msiobj, &summary_Type);
922922
if (!oresult) {
923923
MsiCloseHandle(result);
924924
return NULL;
@@ -1013,7 +1013,7 @@ static PyObject* msiopendb(PyObject *obj, PyObject *args)
10131013
if (status != ERROR_SUCCESS)
10141014
return msierror(status);
10151015

1016-
result = PyObject_NEW(struct msiobj, &msidb_Type);
1016+
result = PyObject_New(struct msiobj, &msidb_Type);
10171017
if (!result) {
10181018
MsiCloseHandle(h);
10191019
return NULL;

0 commit comments

Comments
 (0)