[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 */
 };

AltStyle によって変換されたページ (->オリジナル) /