Commit 6fb3fdec authored by Guido van Rossum's avatar Guido van Rossum

Pytype_GenericAlloc(): round up size so we zap all four bytes of the

__dict__ slot for string subtypes.

subtype_dealloc(): properly use _PyObject_GetDictPtr() to get the
(potentially negative) dict offset.  Don't copy things into local
variables that are used only once.

type_new(): properly calculate a negative dict offset when tp_itemsize
is nonzero.  The __dict__ attribute, if present, is now a calculated
attribute rather than a structure member.
parent 702ca4ff
...@@ -166,11 +166,19 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -166,11 +166,19 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject * PyObject *
PyType_GenericAlloc(PyTypeObject *type, int nitems) PyType_GenericAlloc(PyTypeObject *type, int nitems)
{ {
#define PTRSIZE (sizeof(PyObject *))
int size; int size;
PyObject *obj; PyObject *obj;
/* Inline PyObject_New() so we can zero the memory */ /* Inline PyObject_New() so we can zero the memory */
size = _PyObject_VAR_SIZE(type, nitems); size = _PyObject_VAR_SIZE(type, nitems);
/* Round up size, if necessary, so we fully zero out __dict__ */
if (type->tp_itemsize % PTRSIZE != 0) {
size += PTRSIZE - 1;
size /= PTRSIZE;
size *= PTRSIZE;
}
if (PyType_IS_GC(type)) { if (PyType_IS_GC(type)) {
obj = _PyObject_GC_Malloc(type, nitems); obj = _PyObject_GC_Malloc(type, nitems);
} }
...@@ -202,8 +210,6 @@ PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -202,8 +210,6 @@ PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
static void static void
subtype_dealloc(PyObject *self) subtype_dealloc(PyObject *self)
{ {
int dictoffset = self->ob_type->tp_dictoffset;
int weaklistoffset = self->ob_type->tp_weaklistoffset;
PyTypeObject *type, *base; PyTypeObject *type, *base;
destructor f; destructor f;
...@@ -218,17 +224,19 @@ subtype_dealloc(PyObject *self) ...@@ -218,17 +224,19 @@ subtype_dealloc(PyObject *self)
} }
/* If we added a dict, DECREF it */ /* If we added a dict, DECREF it */
if (dictoffset && !base->tp_dictoffset) { if (type->tp_dictoffset && !base->tp_dictoffset) {
PyObject **dictptr = (PyObject **) ((char *)self + dictoffset); PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr != NULL) {
PyObject *dict = *dictptr; PyObject *dict = *dictptr;
if (dict != NULL) { if (dict != NULL) {
Py_DECREF(dict); Py_DECREF(dict);
*dictptr = NULL; *dictptr = NULL;
} }
} }
}
/* If we added weaklist, we clear it */ /* If we added weaklist, we clear it */
if (weaklistoffset && !base->tp_weaklistoffset) if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
PyObject_ClearWeakRefs(self); PyObject_ClearWeakRefs(self);
/* Finalize GC if the base doesn't do GC and we do */ /* Finalize GC if the base doesn't do GC and we do */
...@@ -579,6 +587,33 @@ solid_base(PyTypeObject *type) ...@@ -579,6 +587,33 @@ solid_base(PyTypeObject *type)
staticforward void object_dealloc(PyObject *); staticforward void object_dealloc(PyObject *);
staticforward int object_init(PyObject *, PyObject *, PyObject *); staticforward int object_init(PyObject *, PyObject *, PyObject *);
static PyObject *
subtype_dict(PyObject *obj, void *context)
{
PyObject **dictptr = _PyObject_GetDictPtr(obj);
PyObject *dict;
if (dictptr == NULL) {
PyErr_SetString(PyExc_AttributeError,
"This object has no __dict__");
return NULL;
}
dict = *dictptr;
if (dict == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
else {
Py_INCREF(dict);
return dict;
}
}
struct getsetlist subtype_getsets[] = {
{"__dict__", subtype_dict, NULL, NULL},
{0},
};
static PyObject * static PyObject *
type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
{ {
...@@ -732,7 +767,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) ...@@ -732,7 +767,6 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
if (slots == NULL && base->tp_dictoffset == 0 && if (slots == NULL && base->tp_dictoffset == 0 &&
(base->tp_setattro == PyObject_GenericSetAttr || (base->tp_setattro == PyObject_GenericSetAttr ||
base->tp_setattro == NULL)) { base->tp_setattro == NULL)) {
nslots++;
add_dict++; add_dict++;
} }
if (slots == NULL && base->tp_weaklistoffset == 0 && if (slots == NULL && base->tp_weaklistoffset == 0 &&
...@@ -829,15 +863,15 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) ...@@ -829,15 +863,15 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
} }
else { else {
if (add_dict) { if (add_dict) {
if (base->tp_itemsize)
type->tp_dictoffset = -sizeof(PyObject *);
else
type->tp_dictoffset = slotoffset; type->tp_dictoffset = slotoffset;
mp->name = "__dict__";
mp->type = T_OBJECT;
mp->offset = slotoffset;
mp->readonly = 1;
mp++;
slotoffset += sizeof(PyObject *); slotoffset += sizeof(PyObject *);
type->tp_getset = subtype_getsets;
} }
if (add_weak) { if (add_weak) {
assert(!base->tp_itemsize);
type->tp_weaklistoffset = slotoffset; type->tp_weaklistoffset = slotoffset;
mp->name = "__weakref__"; mp->name = "__weakref__";
mp->type = T_OBJECT; mp->type = T_OBJECT;
...@@ -848,6 +882,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) ...@@ -848,6 +882,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
} }
} }
type->tp_basicsize = slotoffset; type->tp_basicsize = slotoffset;
type->tp_itemsize = base->tp_itemsize;
type->tp_members = et->members; type->tp_members = et->members;
/* Special case some slots */ /* Special case some slots */
......
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