[Python-checkins] CVS: python/dist/src/Objects descrobject.c,2.14,2.15 typeobject.c,2.82,2.83
Guido van Rossum
gvanrossum@users.sourceforge.net
2001年10月02日 14:25:00 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv30352/Objects
Modified Files:
descrobject.c typeobject.c
Log Message:
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.)
Index: descrobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/descrobject.c,v
retrieving revision 2.14
retrieving revision 2.15
diff -C2 -d -r2.14 -r2.15
*** descrobject.c 2001年09月24日 21:17:50 2.14
--- descrobject.c 2001年10月02日 21:24:57 2.15
***************
*** 39,45 ****
descr_dealloc(PyDescrObject *descr)
{
Py_XDECREF(descr->d_type);
Py_XDECREF(descr->d_name);
! PyObject_DEL(descr);
}
--- 39,46 ----
descr_dealloc(PyDescrObject *descr)
{
+ _PyObject_GC_UNTRACK(descr);
Py_XDECREF(descr->d_type);
Py_XDECREF(descr->d_name);
! PyObject_GC_Del(descr);
}
***************
*** 353,356 ****
--- 354,371 ----
};
+ 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)
***************
*** 374,380 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 389,395 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! descr_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 412,418 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 427,433 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! descr_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 450,456 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 465,471 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! descr_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 488,494 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 503,509 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! descr_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 680,685 ****
proxy_dealloc(proxyobject *pp)
{
Py_DECREF(pp->dict);
! PyObject_DEL(pp);
}
--- 695,701 ----
proxy_dealloc(proxyobject *pp)
{
+ _PyObject_GC_UNTRACK(pp);
Py_DECREF(pp->dict);
! PyObject_GC_Del(pp);
}
***************
*** 696,699 ****
--- 712,729 ----
}
+ 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)
***************
*** 718,724 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 748,754 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! proxy_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 740,747 ****
proxyobject *pp;
! pp = PyObject_NEW(proxyobject, &proxytype);
if (pp != NULL) {
Py_INCREF(dict);
pp->dict = dict;
}
return (PyObject *)pp;
--- 770,778 ----
proxyobject *pp;
! pp = PyObject_GC_New(proxyobject, &proxytype);
if (pp != NULL) {
Py_INCREF(dict);
pp->dict = dict;
+ _PyObject_GC_TRACK(pp);
}
return (PyObject *)pp;
***************
*** 763,769 ****
wrapper_dealloc(wrapperobject *wp)
{
Py_XDECREF(wp->descr);
Py_XDECREF(wp->self);
! PyObject_DEL(wp);
}
--- 794,801 ----
wrapper_dealloc(wrapperobject *wp)
{
+ _PyObject_GC_UNTRACK(wp);
Py_XDECREF(wp->descr);
Py_XDECREF(wp->self);
! PyObject_GC_Del(wp);
}
***************
*** 809,812 ****
--- 841,863 ----
}
+ 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)
***************
*** 831,837 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT, /* tp_flags */
0, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 882,888 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
0, /* tp_doc */
! wrapper_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 858,862 ****
assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
! wp = PyObject_NEW(wrapperobject, &wrappertype);
if (wp != NULL) {
Py_INCREF(descr);
--- 909,913 ----
assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
! wp = PyObject_GC_New(wrapperobject, &wrappertype);
if (wp != NULL) {
Py_INCREF(descr);
***************
*** 864,867 ****
--- 915,919 ----
Py_INCREF(self);
wp->self = self;
+ _PyObject_GC_TRACK(wp);
}
return (PyObject *)wp;
***************
*** 920,923 ****
--- 972,976 ----
propertyobject *gs = (propertyobject *)self;
+ _PyObject_GC_UNTRACK(self);
Py_XDECREF(gs->prop_get);
Py_XDECREF(gs->prop_set);
***************
*** 1013,1016 ****
--- 1066,1089 ----
" 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)
***************
*** 1035,1041 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
property_doc, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 1108,1115 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
! Py_TPFLAGS_BASETYPE, /* tp_flags */
property_doc, /* tp_doc */
! property_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 1054,1057 ****
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
! _PyObject_Del, /* tp_free */
};
--- 1128,1131 ----
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
! _PyObject_GC_Del, /* tp_free */
};
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.82
retrieving revision 2.83
diff -C2 -d -r2.82 -r2.83
*** typeobject.c 2001年10月01日 17:18:22 2.82
--- typeobject.c 2001年10月02日 21:24:57 2.83
***************
*** 266,270 ****
/* Finalize GC if the base doesn't do GC and we do */
if (PyType_IS_GC(type) && !PyType_IS_GC(base))
! PyObject_GC_Fini(self);
/* Call the base tp_dealloc() */
--- 266,270 ----
/* Finalize GC if the base doesn't do GC and we do */
if (PyType_IS_GC(type) && !PyType_IS_GC(base))
! _PyObject_GC_UNTRACK(self);
/* Call the base tp_dealloc() */
***************
*** 865,868 ****
--- 865,870 ----
if (dynamic)
type->tp_flags |= Py_TPFLAGS_DYNAMICTYPE;
+ if (base->tp_flags & Py_TPFLAGS_HAVE_GC)
+ type->tp_flags |= Py_TPFLAGS_HAVE_GC;
/* It's a new-style number unless it specifically inherits any
***************
*** 935,939 ****
if (add_dict) {
if (base->tp_itemsize)
! type->tp_dictoffset = -(long)sizeof(PyObject *);
else
type->tp_dictoffset = slotoffset;
--- 937,942 ----
if (add_dict) {
if (base->tp_itemsize)
! type->tp_dictoffset =
! -(long)sizeof(PyObject *);
else
type->tp_dictoffset = slotoffset;
***************
*** 967,971 ****
/* Always override allocation strategy to use regular heap */
type->tp_alloc = PyType_GenericAlloc;
! type->tp_free = _PyObject_Del;
/* Initialize the rest */
--- 970,980 ----
/* 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_clear = base->tp_clear;
! }
! else
! type->tp_free = _PyObject_Del;
/* Initialize the rest */
***************
*** 1081,1084 ****
--- 1090,1094 ----
/* Assert this is a heap-allocated type object */
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
+ _PyObject_GC_UNTRACK(type);
et = (etype *)type;
Py_XDECREF(type->tp_base);
***************
*** 1103,1106 ****
--- 1113,1182 ----
"type(name, bases, dict) -> a new type";
+ static int
+ type_traverse(PyTypeObject *type, visitproc visit, void *arg)
+ {
+ etype *et;
+ int err;
+
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
+ return 0;
+
+ et = (etype *)type;
+
+ #define VISIT(SLOT) \
+ if (SLOT) { \
+ err = visit((PyObject *)(SLOT), arg); \
+ if (err) \
+ return err; \
+ }
+
+ VISIT(type->tp_dict);
+ VISIT(type->tp_defined);
+ VISIT(type->tp_mro);
+ VISIT(type->tp_bases);
+ VISIT(type->tp_base);
+ VISIT(et->slots);
+
+ #undef VISIT
+
+ return 0;
+ }
+
+ static int
+ type_clear(PyTypeObject *type)
+ {
+ etype *et;
+ PyObject *tmp;
+
+ if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
+ return 0;
+
+ et = (etype *)type;
+
+ #define CLEAR(SLOT) \
+ if (SLOT) { \
+ tmp = (PyObject *)(SLOT); \
+ SLOT = NULL; \
+ Py_DECREF(tmp); \
+ }
+
+ CLEAR(type->tp_dict);
+ CLEAR(type->tp_defined);
+ CLEAR(type->tp_mro);
+ CLEAR(type->tp_bases);
+ CLEAR(type->tp_base);
+ CLEAR(et->slots);
+
+ #undef CLEAR
+
+ return 0;
+ }
+
+ static int
+ type_is_gc(PyTypeObject *type)
+ {
+ return type->tp_flags & Py_TPFLAGS_HEAPTYPE;
+ }
+
PyTypeObject PyType_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 1124,1131 ****
(setattrofunc)type_setattro, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
type_doc, /* tp_doc */
! 0, /* tp_traverse */
! 0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
--- 1200,1208 ----
(setattrofunc)type_setattro, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
! Py_TPFLAGS_BASETYPE, /* tp_flags */
type_doc, /* tp_doc */
! (traverseproc)type_traverse, /* tp_traverse */
! (inquiry)type_clear, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
***************
*** 1143,1146 ****
--- 1220,1225 ----
0, /* tp_alloc */
type_new, /* tp_new */
+ _PyObject_GC_Del, /* tp_free */
+ (inquiry)type_is_gc, /* tp_is_gc */
};
***************
*** 3532,3535 ****
--- 3611,3615 ----
superobject *su = (superobject *)self;
+ _PyObject_GC_UNTRACK(self);
Py_XDECREF(su->obj);
Py_XDECREF(su->type);
***************
*** 3667,3670 ****
--- 3747,3771 ----
" super(C, self).meth(arg)";
+ static int
+ super_traverse(PyObject *self, visitproc visit, void *arg)
+ {
+ superobject *su = (superobject *)self;
+ int err;
+
+ #define VISIT(SLOT) \
+ if (SLOT) { \
+ err = visit((PyObject *)(SLOT), arg); \
+ if (err) \
+ return err; \
+ }
+
+ VISIT(su->obj);
+ VISIT(su->type);
+
+ #undef VISIT
+
+ return 0;
+ }
+
PyTypeObject PySuper_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 3689,3695 ****
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
super_doc, /* tp_doc */
! 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
--- 3790,3797 ----
0, /* tp_setattro */
0, /* tp_as_buffer */
! Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
! Py_TPFLAGS_BASETYPE, /* tp_flags */
super_doc, /* tp_doc */
! super_traverse, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
***************
*** 3708,3711 ****
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
! _PyObject_Del, /* tp_free */
};
--- 3810,3813 ----
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
! _PyObject_GC_Del, /* tp_free */
};