Repaired the debug Windows deaths in test_descr, by allocating enough

pad memory to properly align the __dict__ pointer in all cases.

gcmodule.c/objimpl.h, _PyObject_GC_Malloc:
+ Added a "padding" argument so that this flavor of malloc can allocate
  enough bytes for alignment padding (it can't know this is needed, but
  its callers do).

typeobject.c, PyType_GenericAlloc:
+ Allocated enough bytes to align the __dict__ pointer.
+ Sped and simplified the round-up-to-PTRSIZE logic.
+ Added blank lines so I could parse the if/else blocks <0.7 wink>.
This commit is contained in:
Tim Peters 2001-10-06 19:04:01 +00:00
parent 7254e5a3ed
commit 406fe3b1c0
3 changed files with 33 additions and 21 deletions

View File

@ -230,7 +230,8 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
#define PyObject_IS_GC(o) (PyType_IS_GC((o)->ob_type) && \ #define PyObject_IS_GC(o) (PyType_IS_GC((o)->ob_type) && \
((o)->ob_type->tp_is_gc == NULL || (o)->ob_type->tp_is_gc(o))) ((o)->ob_type->tp_is_gc == NULL || (o)->ob_type->tp_is_gc(o)))
extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *, int); extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *,
int nitems, size_t padding);
extern DL_IMPORT(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, int); extern DL_IMPORT(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, int);
#define PyObject_GC_Resize(type, op, n) \ #define PyObject_GC_Resize(type, op, n) \

View File

@ -798,12 +798,13 @@ _PyObject_GC_UnTrack(PyObject *op)
} }
PyObject * PyObject *
_PyObject_GC_Malloc(PyTypeObject *tp, int size) _PyObject_GC_Malloc(PyTypeObject *tp, int nitems, size_t padding)
{ {
PyObject *op; PyObject *op;
#ifdef WITH_CYCLE_GC #ifdef WITH_CYCLE_GC
const size_t nbytes = sizeof(PyGC_Head) + const size_t basic = (size_t)_PyObject_VAR_SIZE(tp, nitems);
(size_t)_PyObject_VAR_SIZE(tp, size); const size_t nbytes = sizeof(PyGC_Head) + basic + padding;
PyGC_Head *g = PyObject_MALLOC(nbytes); PyGC_Head *g = PyObject_MALLOC(nbytes);
if (g == NULL) if (g == NULL)
return (PyObject *)PyErr_NoMemory(); return (PyObject *)PyErr_NoMemory();
@ -820,7 +821,7 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int size)
} }
op = FROM_GC(g); op = FROM_GC(g);
#else #else
op = PyObject_MALLOC(_PyObject_VAR_SIZE(tp, size)); op = PyObject_MALLOC(_PyObject_VAR_SIZE(tp, nitems) + padding);
if (op == NULL) if (op == NULL)
return (PyObject *)PyErr_NoMemory(); return (PyObject *)PyErr_NoMemory();
@ -831,14 +832,14 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int size)
PyObject * PyObject *
_PyObject_GC_New(PyTypeObject *tp) _PyObject_GC_New(PyTypeObject *tp)
{ {
PyObject *op = _PyObject_GC_Malloc(tp, 0); PyObject *op = _PyObject_GC_Malloc(tp, 0, 0);
return PyObject_INIT(op, tp); return PyObject_INIT(op, tp);
} }
PyVarObject * PyVarObject *
_PyObject_GC_NewVar(PyTypeObject *tp, int size) _PyObject_GC_NewVar(PyTypeObject *tp, int size)
{ {
PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(tp, size); PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(tp, size, 0);
return PyObject_INIT_VAR(op, tp, size); return PyObject_INIT_VAR(op, tp, size);
} }

View File

@ -192,32 +192,42 @@ PyType_GenericAlloc(PyTypeObject *type, int nitems)
{ {
#define PTRSIZE (sizeof(PyObject *)) #define PTRSIZE (sizeof(PyObject *))
int size; size_t size = (size_t)_PyObject_VAR_SIZE(type, nitems);
size_t padding = 0;
PyObject *obj; PyObject *obj;
/* Inline PyObject_New() so we can zero the memory */ /* Round up size, if necessary, so that the __dict__ pointer
size = _PyObject_VAR_SIZE(type, nitems); following the variable part is properly aligned for the platform.
/* Round up size, if necessary, so we fully zero out __dict__ */ This is needed only for types with a vrbl number of items
if (type->tp_itemsize % PTRSIZE != 0) { before the __dict__ pointer == types that record the dict offset
size += PTRSIZE - 1; as a negative offset from the end of the object. If tp_dictoffset
size /= PTRSIZE; is 0, there is no __dict__; if positive, tp_dict was declared in a C
size *= PTRSIZE; struct so the compiler already took care of aligning it. */
if (type->tp_dictoffset < 0) {
padding = PTRSIZE - size % PTRSIZE;
if (padding == PTRSIZE)
padding = 0;
size += padding;
} }
if (PyType_IS_GC(type)) {
obj = _PyObject_GC_Malloc(type, nitems); if (PyType_IS_GC(type))
} obj = _PyObject_GC_Malloc(type, nitems, padding);
else { else
obj = PyObject_MALLOC(size); obj = PyObject_MALLOC(size);
}
if (obj == NULL) if (obj == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
memset(obj, '\0', size); memset(obj, '\0', size);
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
Py_INCREF(type); Py_INCREF(type);
if (type->tp_itemsize == 0) if (type->tp_itemsize == 0)
PyObject_INIT(obj, type); PyObject_INIT(obj, type);
else else
(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems); (void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
if (PyType_IS_GC(type)) if (PyType_IS_GC(type))
_PyObject_GC_TRACK(obj); _PyObject_GC_TRACK(obj);
return obj; return obj;