Enable GC for new-style instances. This touches lots of files, since

many types were subclassable but had a xxx_dealloc function that
called PyObject_DEL(self) directly instead of deferring to
self->ob_type->tp_free(self).  It is permissible to set tp_free in the
type object directly to _PyObject_Del, for non-GC types, or to
_PyObject_GC_Del, for GC types.  Still, PyObject_DEL was a tad faster,
so I'm fearing that our pystone rating is going down again.  I'm not
sure if doing something like

void xxx_dealloc(PyObject *self)
{
	if (PyXxxCheckExact(self))
		PyObject_DEL(self);
	else
		self->ob_type->tp_free(self);
}

is any faster than always calling the else branch, so I haven't
attempted that -- however those types whose own dealloc is fancier
(int, float, unicode) do use this pattern.
This commit is contained in:
Guido van Rossum 2001-10-05 20:51:39 +00:00
parent be63884d50
commit 9475a2310d
13 changed files with 90 additions and 26 deletions

View file

@ -229,7 +229,36 @@ PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
return type->tp_alloc(type, 0);
}
/* Helper for subtyping */
/* Helpers for subtyping */
static int
subtype_traverse(PyObject *self, visitproc visit, void *arg)
{
PyTypeObject *type, *base;
traverseproc f;
int err;
/* Find the nearest base with a different tp_traverse */
type = self->ob_type;
base = type->tp_base;
while ((f = base->tp_traverse) == subtype_traverse) {
base = base->tp_base;
assert(base);
}
if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr) {
err = visit(*dictptr, arg);
if (err)
return err;
}
}
if (f)
return f(self, visit, arg);
return 0;
}
static void
subtype_dealloc(PyObject *self)
@ -968,11 +997,16 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
}
type->tp_dealloc = subtype_dealloc;
/* Enable GC unless there are really no instance variables possible */
if (!(type->tp_basicsize == sizeof(PyObject) &&
type->tp_itemsize == 0))
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
/* Always override allocation strategy to use regular heap */
type->tp_alloc = PyType_GenericAlloc;
if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
type->tp_free = _PyObject_GC_Del;
type->tp_traverse = base->tp_traverse;
type->tp_traverse = subtype_traverse;
type->tp_clear = base->tp_clear;
}
else
@ -1097,7 +1131,6 @@ type_dealloc(PyTypeObject *type)
Py_XDECREF(type->tp_bases);
Py_XDECREF(type->tp_mro);
Py_XDECREF(type->tp_defined);
/* XXX more? */
Py_XDECREF(et->name);
Py_XDECREF(et->slots);
type->ob_type->tp_free((PyObject *)type);
@ -1291,12 +1324,6 @@ object_hash(PyObject *self)
return _Py_HashPointer(self);
}
static void
object_free(PyObject *self)
{
PyObject_Del(self);
}
static PyObject *
object_get_class(PyObject *self, void *closure)
{
@ -1446,7 +1473,7 @@ PyTypeObject PyBaseObject_Type = {
object_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
object_free, /* tp_free */
_PyObject_Del, /* tp_free */
};