diff options
author | Guido van Rossum <guido@python.org> | 2001-10-02 21:24:57 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-10-02 21:24:57 (GMT) |
commit | 048eb75c2dca8bf6d483b290c901a53510c9b78a (patch) | |
tree | 4ffa13f63991488114f0e5c0d57983c0d80481e3 /Objects/descrobject.c | |
parent | 0481d24dd51bf3a346b432e1c065ed027bccb5c4 (diff) | |
download | cpython-048eb75c2dca8bf6d483b290c901a53510c9b78a.zip cpython-048eb75c2dca8bf6d483b290c901a53510c9b78a.tar.gz cpython-048eb75c2dca8bf6d483b290c901a53510c9b78a.tar.bz2 |
Add Garbage Collection support to new-style classes (not yet to their
instances).
Also added GC support to various auxiliary types: super, property,
descriptors, wrappers, dictproxy. (Only type objects have a tp_clear
field; the other types are.)
One change was necessary to the GC infrastructure. We have statically
allocated type objects that don't have a GC header (and can't easily
be given one) and heap-allocated type objects that do have a GC
header. Giving these different metatypes would be really ugly: I
tried, and I had to modify pickle.py, cPickle.c, copy.py, add a new
invent a new name for the new metatype and make it a built-in, change
affected tests... In short, a mess. So instead, we add a new type
slot tp_is_gc, which is a simple Boolean function that determines
whether a particular instance has GC headers or not. This slot is
only relevant for types that have the (new) GC flag bit set. If the
tp_is_gc slot is NULL (by far the most common case), all instances of
the type are deemed to have GC headers. This slot is called by the
PyObject_IS_GC() macro (which is only used twice, both times in
gcmodule.c).
I also changed the extern declarations for a bunch of GC-related
functions (_PyObject_GC_Del etc.): these always exist but objimpl.h
only declared them when WITH_CYCLE_GC was defined, but I needed to be
able to reference them without #ifdefs. (When WITH_CYCLE_GC is not
defined, they do the same as their non-GC counterparts anyway.)
Diffstat (limited to 'Objects/descrobject.c')
-rw-r--r-- | Objects/descrobject.c | 114 |
1 files changed, 94 insertions, 20 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c index fea67f3..3a65902 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -38,9 +38,10 @@ typedef struct { static void descr_dealloc(PyDescrObject *descr) { + _PyObject_GC_UNTRACK(descr); Py_XDECREF(descr->d_type); Py_XDECREF(descr->d_name); - PyObject_DEL(descr); + PyObject_GC_Del(descr); } static char * @@ -352,6 +353,20 @@ static PyGetSetDef wrapper_getset[] = { {0} }; +static int +descr_traverse(PyObject *self, visitproc visit, void *arg) +{ + PyDescrObject *descr = (PyDescrObject *)self; + int err; + + if (descr->d_type) { + err = visit((PyObject *)(descr->d_type), arg); + if (err) + return err; + } + return 0; +} + static PyTypeObject PyMethodDescr_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -373,9 +388,9 @@ static PyTypeObject PyMethodDescr_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + descr_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -411,9 +426,9 @@ static PyTypeObject PyMemberDescr_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + descr_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -449,9 +464,9 @@ static PyTypeObject PyGetSetDescr_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + descr_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -487,9 +502,9 @@ static PyTypeObject PyWrapperDescr_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + descr_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -679,8 +694,9 @@ static PyMethodDef proxy_methods[] = { static void proxy_dealloc(proxyobject *pp) { + _PyObject_GC_UNTRACK(pp); Py_DECREF(pp->dict); - PyObject_DEL(pp); + PyObject_GC_Del(pp); } static PyObject * @@ -695,6 +711,20 @@ proxy_str(proxyobject *pp) return PyObject_Str(pp->dict); } +static int +proxy_traverse(PyObject *self, visitproc visit, void *arg) +{ + proxyobject *pp = (proxyobject *)self; + int err; + + if (pp->dict) { + err = visit(pp->dict, arg); + if (err) + return err; + } + return 0; +} + PyTypeObject proxytype = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ @@ -717,9 +747,9 @@ PyTypeObject proxytype = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + proxy_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -739,10 +769,11 @@ PyDictProxy_New(PyObject *dict) { proxyobject *pp; - pp = PyObject_NEW(proxyobject, &proxytype); + pp = PyObject_GC_New(proxyobject, &proxytype); if (pp != NULL) { Py_INCREF(dict); pp->dict = dict; + _PyObject_GC_TRACK(pp); } return (PyObject *)pp; } @@ -762,9 +793,10 @@ typedef struct { static void wrapper_dealloc(wrapperobject *wp) { + _PyObject_GC_UNTRACK(wp); Py_XDECREF(wp->descr); Py_XDECREF(wp->self); - PyObject_DEL(wp); + PyObject_GC_Del(wp); } static PyMethodDef wrapper_methods[] = { @@ -808,6 +840,25 @@ wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) return (*wrapper)(self, args, wp->descr->d_wrapped); } +static int +wrapper_traverse(PyObject *self, visitproc visit, void *arg) +{ + wrapperobject *wp = (wrapperobject *)self; + int err; + + if (wp->descr) { + err = visit((PyObject *)(wp->descr), arg); + if (err) + return err; + } + if (wp->self) { + err = visit(wp->self, arg); + if (err) + return err; + } + return 0; +} + PyTypeObject wrappertype = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ @@ -830,9 +881,9 @@ PyTypeObject wrappertype = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - 0, /* tp_traverse */ + wrapper_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -857,12 +908,13 @@ PyWrapper_New(PyObject *d, PyObject *self) descr = (PyWrapperDescrObject *)d; assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type))); - wp = PyObject_NEW(wrapperobject, &wrappertype); + wp = PyObject_GC_New(wrapperobject, &wrappertype); if (wp != NULL) { Py_INCREF(descr); wp->descr = descr; Py_INCREF(self); wp->self = self; + _PyObject_GC_TRACK(wp); } return (PyObject *)wp; } @@ -919,6 +971,7 @@ property_dealloc(PyObject *self) { propertyobject *gs = (propertyobject *)self; + _PyObject_GC_UNTRACK(self); Py_XDECREF(gs->prop_get); Py_XDECREF(gs->prop_set); Py_XDECREF(gs->prop_del); @@ -1012,6 +1065,26 @@ static char property_doc[] = " def delx(self): del self.__x\n" " x = property(getx, setx, delx, \"I'm the 'x' property.\")"; +static int +property_traverse(PyObject *self, visitproc visit, void *arg) +{ + propertyobject *pp = (propertyobject *)self; + int err; + +#define VISIT(SLOT) \ + if (pp->SLOT) { \ + err = visit((PyObject *)(pp->SLOT), arg); \ + if (err) \ + return err; \ + } + + VISIT(prop_get); + VISIT(prop_set); + VISIT(prop_del); + + return 0; +} + PyTypeObject PyProperty_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ @@ -1034,9 +1107,10 @@ PyTypeObject PyProperty_Type = { PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE, /* tp_flags */ property_doc, /* tp_doc */ - 0, /* tp_traverse */ + property_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -1053,5 +1127,5 @@ PyTypeObject PyProperty_Type = { property_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - _PyObject_Del, /* tp_free */ + _PyObject_GC_Del, /* tp_free */ }; |