Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f2a67da

Browse files
committed
Guido suggests, and I agree, to insist that SIZEOF_VOID_P be a power of 2.
This simplifies the rounding in _PyObject_VAR_SIZE, allows to restore the pre-rounding calling sequence, and allows some nice little simplifications in its callers. I'm still making it return a size_t, though.
1 parent 0a1fc4e commit f2a67da

4 files changed

Lines changed: 32 additions & 48 deletions

File tree

Include/objimpl.h

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -173,40 +173,36 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
173173

174174
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
175175

176-
/* _PyObject_VAR_SIZE computes the amount of memory allocated for a vrbl-
177-
size object with nitems items, exclusive of gc overhead (if any). The
178-
value is rounded up to the closest multiple of sizeof(void *), in order
179-
to ensure that pointer fields at the end of the object are correctly
180-
aligned for the platform (this is of special importance for subclasses
181-
of, e.g., str or long, so that pointers can be stored after the embedded
182-
data).
183-
184-
Note that there's no memory wastage in doing this, as malloc has to
185-
return (at worst) pointer-aligned memory anyway
186-
187-
However, writing the macro to *return* the result is clumsy due to the
188-
calculations needed. Instead you must pass the result lvalue as the first
189-
argument, and it should be of type size_t (both because that's the
190-
correct conceptual type, and because using an unsigned type allows the
191-
compiler to generate faster code for the mod computation inside the
192-
macro).
176+
/* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a
177+
vrbl-size object with nitems items, exclusive of gc overhead (if any). The
178+
value is rounded up to the closest multiple of sizeof(void *), in order to
179+
ensure that pointer fields at the end of the object are correctly aligned
180+
for the platform (this is of special importance for subclasses of, e.g.,
181+
str or long, so that pointers can be stored after the embedded data).
182+
183+
Note that there's no memory wastage in doing this, as malloc has to
184+
return (at worst) pointer-aligned memory anyway.
193185
*/
194-
#define _PyObject_VAR_SIZE(result, typeobj, nitems) \
195-
do { \
196-
size_t mod; \
197-
(result) = (size_t) (typeobj)->tp_basicsize; \
198-
(result) += (size_t) ((nitems)*(typeobj)->tp_itemsize); \
199-
mod = (result) % SIZEOF_VOID_P; \
200-
if (mod) \
201-
(result) += SIZEOF_VOID_P - mod; \
202-
} while(0)
186+
#if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0
187+
# error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2"
188+
#endif
189+
190+
#define _PyObject_VAR_SIZE(typeobj, nitems) \
191+
(size_t) \
192+
( ( (typeobj)->tp_basicsize + \
193+
(nitems)*(typeobj)->tp_itemsize + \
194+
(SIZEOF_VOID_P - 1) \
195+
) & ~(SIZEOF_VOID_P - 1) \
196+
)
203197

204198
#define PyObject_NEW(type, typeobj) \
205199
( (type *) PyObject_Init( \
206200
(PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) )
207201

208-
#define PyObject_NEW_VAR(type, typeobj, nitems) \
209-
((type *) _PyObject_NewVar(typeobj, nitems))
202+
#define PyObject_NEW_VAR(type, typeobj, n) \
203+
( (type *) PyObject_InitVar( \
204+
(PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE((typeobj),(n)) ),\
205+
(typeobj), (n)) )
210206

211207
#define PyObject_DEL(op) PyObject_FREE(op)
212208

Modules/gcmodule.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -801,14 +801,10 @@ PyObject *
801801
_PyObject_GC_Malloc(PyTypeObject *tp, int nitems)
802802
{
803803
PyObject *op;
804-
size_t basicsize;
804+
const size_t basicsize = _PyObject_VAR_SIZE(tp, nitems);
805805
#ifdef WITH_CYCLE_GC
806-
size_t nbytes;
807-
PyGC_Head *g;
808-
809-
_PyObject_VAR_SIZE(basicsize, tp, nitems);
810-
nbytes = sizeof(PyGC_Head) + basicsize;
811-
g = PyObject_MALLOC(nbytes);
806+
const size_t nbytes = sizeof(PyGC_Head) + basicsize;
807+
PyGC_Head *g = PyObject_MALLOC(nbytes);
812808
if (g == NULL)
813809
return (PyObject *)PyErr_NoMemory();
814810
g->gc_next = NULL;
@@ -824,7 +820,6 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int nitems)
824820
}
825821
op = FROM_GC(g);
826822
#else
827-
_PyObject_VAR_SIZE(basicsize, tp, nitems);
828823
op = PyObject_MALLOC(basicsize);
829824
if (op == NULL)
830825
return (PyObject *)PyErr_NoMemory();
@@ -850,17 +845,14 @@ _PyObject_GC_NewVar(PyTypeObject *tp, int nitems)
850845
PyVarObject *
851846
_PyObject_GC_Resize(PyVarObject *op, int nitems)
852847
{
853-
size_t basicsize;
848+
const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems);
854849
#ifdef WITH_CYCLE_GC
855850
PyGC_Head *g = AS_GC(op);
856-
857-
_PyObject_VAR_SIZE(basicsize, op->ob_type, nitems);
858851
g = PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize);
859852
if (g == NULL)
860853
return (PyVarObject *)PyErr_NoMemory();
861854
op = (PyVarObject *) FROM_GC(g);
862855
#else
863-
_PyObject_VAR_SIZE(basicsize, op->ob_type, nitems);
864856
op = PyObject_REALLOC(op, basicsize);
865857
if (op == NULL)
866858
return (PyVarObject *)PyErr_NoMemory();

Objects/object.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,7 @@ PyVarObject *
130130
_PyObject_NewVar(PyTypeObject *tp, int nitems)
131131
{
132132
PyVarObject *op;
133-
size_t size;
134-
135-
_PyObject_VAR_SIZE(size, tp, nitems);
133+
const size_t size = _PyObject_VAR_SIZE(tp, nitems);
136134
op = (PyVarObject *) PyObject_MALLOC(size);
137135
if (op == NULL)
138136
return (PyVarObject *)PyErr_NoMemory();
@@ -1158,8 +1156,8 @@ _PyObject_GetDictPtr(PyObject *obj)
11581156
if (dictoffset == 0)
11591157
return NULL;
11601158
if (dictoffset < 0) {
1161-
size_t size;
1162-
_PyObject_VAR_SIZE(size, tp, ((PyVarObject *)obj)->ob_size);
1159+
const size_t size = _PyObject_VAR_SIZE(tp,
1160+
((PyVarObject *)obj)->ob_size);
11631161
dictoffset += (long)size;
11641162
assert(dictoffset > 0);
11651163
assert(dictoffset % SIZEOF_VOID_P == 0);

Objects/typeobject.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,7 @@ PyObject *
191191
PyType_GenericAlloc(PyTypeObject *type, int nitems)
192192
{
193193
PyObject *obj;
194-
size_t size;
195-
196-
_PyObject_VAR_SIZE(size, type, nitems);
194+
const size_t size = _PyObject_VAR_SIZE(type, nitems);
197195

198196
if (PyType_IS_GC(type))
199197
obj = _PyObject_GC_Malloc(type, nitems);

0 commit comments

Comments
 (0)