Commit f2a67dac authored by Tim Peters's avatar Tim Peters

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.
parent 0a1fc4e3
...@@ -173,40 +173,36 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *); ...@@ -173,40 +173,36 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize ) #define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
/* _PyObject_VAR_SIZE computes the amount of memory allocated for a vrbl- /* _PyObject_VAR_SIZE returns the number of bytes (as size_t) allocated for a
size object with nitems items, exclusive of gc overhead (if any). The 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 value is rounded up to the closest multiple of sizeof(void *), in order to
to ensure that pointer fields at the end of the object are correctly ensure that pointer fields at the end of the object are correctly aligned
aligned for the platform (this is of special importance for subclasses for the platform (this is of special importance for subclasses of, e.g.,
of, e.g., str or long, so that pointers can be stored after the embedded str or long, so that pointers can be stored after the embedded data).
data).
Note that there's no memory wastage in doing this, as malloc has to Note that there's no memory wastage in doing this, as malloc has to
return (at worst) pointer-aligned memory anyway return (at worst) pointer-aligned memory anyway.
However, writing the macro to *return* the result is clumsy due to the
calculations needed. Instead you must pass the result lvalue as the first
argument, and it should be of type size_t (both because that's the
correct conceptual type, and because using an unsigned type allows the
compiler to generate faster code for the mod computation inside the
macro).
*/ */
#define _PyObject_VAR_SIZE(result, typeobj, nitems) \ #if ((SIZEOF_VOID_P - 1) & SIZEOF_VOID_P) != 0
do { \ # error "_PyObject_VAR_SIZE requires SIZEOF_VOID_P be a power of 2"
size_t mod; \ #endif
(result) = (size_t) (typeobj)->tp_basicsize; \
(result) += (size_t) ((nitems)*(typeobj)->tp_itemsize); \ #define _PyObject_VAR_SIZE(typeobj, nitems) \
mod = (result) % SIZEOF_VOID_P; \ (size_t) \
if (mod) \ ( ( (typeobj)->tp_basicsize + \
(result) += SIZEOF_VOID_P - mod; \ (nitems)*(typeobj)->tp_itemsize + \
} while(0) (SIZEOF_VOID_P - 1) \
) & ~(SIZEOF_VOID_P - 1) \
)
#define PyObject_NEW(type, typeobj) \ #define PyObject_NEW(type, typeobj) \
( (type *) PyObject_Init( \ ( (type *) PyObject_Init( \
(PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) ) (PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) )
#define PyObject_NEW_VAR(type, typeobj, nitems) \ #define PyObject_NEW_VAR(type, typeobj, n) \
((type *) _PyObject_NewVar(typeobj, nitems)) ( (type *) PyObject_InitVar( \
(PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE((typeobj),(n)) ),\
(typeobj), (n)) )
#define PyObject_DEL(op) PyObject_FREE(op) #define PyObject_DEL(op) PyObject_FREE(op)
......
...@@ -801,14 +801,10 @@ PyObject * ...@@ -801,14 +801,10 @@ PyObject *
_PyObject_GC_Malloc(PyTypeObject *tp, int nitems) _PyObject_GC_Malloc(PyTypeObject *tp, int nitems)
{ {
PyObject *op; PyObject *op;
size_t basicsize; const size_t basicsize = _PyObject_VAR_SIZE(tp, nitems);
#ifdef WITH_CYCLE_GC #ifdef WITH_CYCLE_GC
size_t nbytes; const size_t nbytes = sizeof(PyGC_Head) + basicsize;
PyGC_Head *g; PyGC_Head *g = PyObject_MALLOC(nbytes);
_PyObject_VAR_SIZE(basicsize, tp, nitems);
nbytes = sizeof(PyGC_Head) + basicsize;
g = PyObject_MALLOC(nbytes);
if (g == NULL) if (g == NULL)
return (PyObject *)PyErr_NoMemory(); return (PyObject *)PyErr_NoMemory();
g->gc_next = NULL; g->gc_next = NULL;
...@@ -824,7 +820,6 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int nitems) ...@@ -824,7 +820,6 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int nitems)
} }
op = FROM_GC(g); op = FROM_GC(g);
#else #else
_PyObject_VAR_SIZE(basicsize, tp, nitems);
op = PyObject_MALLOC(basicsize); op = PyObject_MALLOC(basicsize);
if (op == NULL) if (op == NULL)
return (PyObject *)PyErr_NoMemory(); return (PyObject *)PyErr_NoMemory();
...@@ -850,17 +845,14 @@ _PyObject_GC_NewVar(PyTypeObject *tp, int nitems) ...@@ -850,17 +845,14 @@ _PyObject_GC_NewVar(PyTypeObject *tp, int nitems)
PyVarObject * PyVarObject *
_PyObject_GC_Resize(PyVarObject *op, int nitems) _PyObject_GC_Resize(PyVarObject *op, int nitems)
{ {
size_t basicsize; const size_t basicsize = _PyObject_VAR_SIZE(op->ob_type, nitems);
#ifdef WITH_CYCLE_GC #ifdef WITH_CYCLE_GC
PyGC_Head *g = AS_GC(op); PyGC_Head *g = AS_GC(op);
_PyObject_VAR_SIZE(basicsize, op->ob_type, nitems);
g = PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); g = PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize);
if (g == NULL) if (g == NULL)
return (PyVarObject *)PyErr_NoMemory(); return (PyVarObject *)PyErr_NoMemory();
op = (PyVarObject *) FROM_GC(g); op = (PyVarObject *) FROM_GC(g);
#else #else
_PyObject_VAR_SIZE(basicsize, op->ob_type, nitems);
op = PyObject_REALLOC(op, basicsize); op = PyObject_REALLOC(op, basicsize);
if (op == NULL) if (op == NULL)
return (PyVarObject *)PyErr_NoMemory(); return (PyVarObject *)PyErr_NoMemory();
......
...@@ -130,9 +130,7 @@ PyVarObject * ...@@ -130,9 +130,7 @@ PyVarObject *
_PyObject_NewVar(PyTypeObject *tp, int nitems) _PyObject_NewVar(PyTypeObject *tp, int nitems)
{ {
PyVarObject *op; PyVarObject *op;
size_t size; const size_t size = _PyObject_VAR_SIZE(tp, nitems);
_PyObject_VAR_SIZE(size, tp, nitems);
op = (PyVarObject *) PyObject_MALLOC(size); op = (PyVarObject *) PyObject_MALLOC(size);
if (op == NULL) if (op == NULL)
return (PyVarObject *)PyErr_NoMemory(); return (PyVarObject *)PyErr_NoMemory();
...@@ -1158,8 +1156,8 @@ _PyObject_GetDictPtr(PyObject *obj) ...@@ -1158,8 +1156,8 @@ _PyObject_GetDictPtr(PyObject *obj)
if (dictoffset == 0) if (dictoffset == 0)
return NULL; return NULL;
if (dictoffset < 0) { if (dictoffset < 0) {
size_t size; const size_t size = _PyObject_VAR_SIZE(tp,
_PyObject_VAR_SIZE(size, tp, ((PyVarObject *)obj)->ob_size); ((PyVarObject *)obj)->ob_size);
dictoffset += (long)size; dictoffset += (long)size;
assert(dictoffset > 0); assert(dictoffset > 0);
assert(dictoffset % SIZEOF_VOID_P == 0); assert(dictoffset % SIZEOF_VOID_P == 0);
......
...@@ -191,9 +191,7 @@ PyObject * ...@@ -191,9 +191,7 @@ PyObject *
PyType_GenericAlloc(PyTypeObject *type, int nitems) PyType_GenericAlloc(PyTypeObject *type, int nitems)
{ {
PyObject *obj; PyObject *obj;
size_t size; const size_t size = _PyObject_VAR_SIZE(type, nitems);
_PyObject_VAR_SIZE(size, type, nitems);
if (PyType_IS_GC(type)) if (PyType_IS_GC(type))
obj = _PyObject_GC_Malloc(type, nitems); obj = _PyObject_GC_Malloc(type, nitems);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment