Round 1 of Neil Schemenauer's GC patches:

This patch adds the type methods traverse and clear necessary for GC
implementation.
diff --git a/Include/object.h b/Include/object.h
index f6ceba5..e18e0e8 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -145,6 +145,8 @@
 typedef int (*getsegcountproc) Py_PROTO((PyObject *, int *));
 typedef int (*getcharbufferproc) Py_PROTO((PyObject *, int, const char **));
 typedef int (*objobjproc) Py_PROTO((PyObject *, PyObject *));
+typedef int (*visitproc) Py_PROTO((PyObject *, void *));
+typedef int (*traverseproc) Py_PROTO((PyObject *, visitproc, void *));
 
 typedef struct {
 	binaryfunc nb_add;
@@ -243,9 +245,13 @@
 
 	char *tp_doc; /* Documentation string */
 
+	/* call function for all accessible objects */
+	traverseproc tp_traverse;
+	
+	/* delete references to contained objects */
+	inquiry tp_clear;
+
 	/* More spares */
-	long tp_xxx5;
-	long tp_xxx6;
 	long tp_xxx7;
 	long tp_xxx8;
 
diff --git a/Objects/classobject.c b/Objects/classobject.c
index bd95bc0..18908f3 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -387,6 +387,43 @@
 	return res;
 }
 
+static int
+class_traverse(PyClassObject *o, visitproc visit, void *arg)
+{
+	int err;
+	if (o->cl_bases) {
+		err = visit(o->cl_bases, arg);
+		if (err)
+			return err;
+	}
+	if (o->cl_dict) {
+		err = visit(o->cl_dict, arg);
+		if (err)
+			return err;
+	}
+	if (o->cl_name) {
+		err = visit(o->cl_name, arg);
+		if (err)
+			return err;
+	}
+	if (o->cl_getattr) {
+		err = visit(o->cl_getattr, arg);
+		if (err)
+			return err;
+	}
+	if (o->cl_setattr) {
+		err = visit(o->cl_setattr, arg);
+		if (err)
+			return err;
+	}
+	if (o->cl_delattr) {
+		err = visit(o->cl_delattr, arg);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
 PyTypeObject PyClass_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
@@ -407,6 +444,10 @@
 	(reprfunc)class_str, /*tp_str*/
 	(getattrofunc)class_getattr, /*tp_getattro*/
 	(setattrofunc)class_setattr, /*tp_setattro*/
+	0,		/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,		/* tp_doc */
+	(traverseproc)class_traverse,	/* tp_traverse */
 };
 
 int
@@ -849,6 +890,23 @@
 	return outcome;
 }
 
+static int
+instance_traverse(PyInstanceObject *o, visitproc visit, void *arg)
+{
+	int err;
+	if (o->in_class) {
+		err = visit((PyObject *)(o->in_class), arg);
+		if (err)
+			return err;
+	}
+	if (o->in_dict) {
+		err = visit(o->in_dict, arg);
+		if (err)
+			return err;
+	}
+	return 1;
+}
+
 static PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr;
 
 static int
@@ -1472,7 +1530,9 @@
 	(getattrofunc)instance_getattr, /*tp_getattro*/
 	(setattrofunc)instance_setattr, /*tp_setattro*/
         0, /* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT, /*tp_flags */
+	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,		/* tp_doc */
+	(traverseproc)instance_traverse,	/* tp_traverse */
 };
 
 
@@ -1662,6 +1722,28 @@
 	return x ^ y;
 }
 
+static int
+instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg)
+{
+	int err;
+	if (im->im_func) {
+		err = visit(im->im_func, arg);
+		if (err)
+			return err;
+	}
+	if (im->im_self) {
+		err = visit(im->im_self, arg);
+		if (err)
+			return err;
+	}
+	if (im->im_class) {
+		err = visit(im->im_class, arg);
+		if (err)
+			return err;
+	}
+	return 1;
+}
+
 PyTypeObject PyMethod_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
@@ -1682,6 +1764,10 @@
 	0,			/*tp_str*/
 	(getattrofunc)instancemethod_getattr, /*tp_getattro*/
 	0,			/*tp_setattro*/
+	0,			/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,			/* tp_doc */
+	(traverseproc)instancemethod_traverse,	/* tp_traverse */
 };
 
 /* Clear out the free list */
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 6e7fa3d..2d33b92 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1038,6 +1038,31 @@
 	return Py_None;
 }
 
+static int
+dict_traverse(PyObject *op, visitproc visit, void *arg)
+{
+	int i = 0, err;
+	PyObject *pk;
+	PyObject *pv;
+
+	while (PyDict_Next(op, &i, &pk, &pv)) {
+		err = visit(pk, arg);
+		if (err)
+			return err;
+		err = visit(pv, arg);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int
+dict_tp_clear(PyObject *op)
+{
+	PyDict_Clear(op);
+	return 0;
+}
+
 static PyMethodDef mapp_methods[] = {
 	{"has_key",	(PyCFunction)dict_has_key,      METH_VARARGS},
 	{"keys",	(PyCFunction)dict_keys},
@@ -1073,6 +1098,16 @@
 	0,			/*tp_as_number*/
 	0,			/*tp_as_sequence*/
 	&dict_as_mapping,	/*tp_as_mapping*/
+	0,		/* tp_hash */
+	0,		/* tp_call */
+	0,		/* tp_str */
+	0,		/* tp_getattro */
+	0,		/* tp_setattro */
+	0,		/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,		/* tp_doc */
+	(traverseproc)dict_traverse,	/* tp_traverse */
+	(inquiry)dict_tp_clear,		/* tp_clear */
 };
 
 /* For backward compatibility with old dictionary interface */
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index a5e15cc..142c7e7 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -239,6 +239,38 @@
 	return h;
 }
 
+static int
+func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
+{
+	int err;
+	if (f->func_code) {
+		err = visit(f->func_code, arg);
+		if (err)
+			return err;
+	}
+	if (f->func_globals) {
+		err = visit(f->func_globals, arg);
+		if (err)
+			return err;
+	}
+	if (f->func_defaults) {
+		err = visit(f->func_defaults, arg);
+		if (err)
+			return err;
+	}
+	if (f->func_doc) {
+		err = visit(f->func_doc, arg);
+		if (err)
+			return err;
+	}
+	if (f->func_name) {
+		err = visit(f->func_name, arg);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
 PyTypeObject PyFunction_Type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
@@ -255,4 +287,12 @@
 	0,		/*tp_as_sequence*/
 	0,		/*tp_as_mapping*/
 	(hashfunc)func_hash, /*tp_hash*/
+	0,		/*tp_call*/
+	0,		/*tp_str*/
+	0,		/*tp_getattro*/
+	0,		/*tp_setattro*/
+	0,		/* tp_as_buffer */
+	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,		/* tp_doc */
+	(traverseproc)func_traverse,	/* tp_traverse */
 };
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 163ba2a..65dfb18 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -1418,6 +1418,30 @@
 	return NULL;
 }
 
+static int
+list_traverse(PyListObject *o, visitproc visit, void *arg)
+{
+	int i, err;
+	PyObject *x;
+
+	for (i = o->ob_size; --i >= 0; ) {
+		x = o->ob_item[i];
+		if (x != NULL) {
+			err = visit(x, arg);
+			if (err)
+				return err;
+		}
+	}
+	return 0;
+}
+
+static int
+list_clear(PyListObject *lp)
+{
+	(void) PyList_SetSlice((PyObject *)lp, 0, lp->ob_size, 0);
+	return 0;
+}
+
 static char append_doc[] =
 "L.append(object) -- append object to end";
 static char extend_doc[] =
@@ -1491,6 +1515,9 @@
 	0,		/*tp_setattro*/
 	0,		/*tp_as_buffer*/
 	Py_TPFLAGS_DEFAULT,	/*tp_flags*/
+ 	0,		/* tp_doc */
+ 	(traverseproc)list_traverse,	/* tp_traverse */
+ 	(inquiry)list_clear,	/* tp_clear */
 };
 
 
@@ -1567,5 +1594,7 @@
 	0,		/*tp_setattro*/
 	0,		/*tp_as_buffer*/
 	Py_TPFLAGS_DEFAULT,	/*tp_flags*/
+ 	0,		/* tp_doc */
+ 	(traverseproc)list_traverse,	/* tp_traverse */
 };
 
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index f89fa36..bbb56b1 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -420,6 +420,23 @@
 	return (PyObject *) np;
 }
 
+static int
+tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
+{
+	int i, err;
+	PyObject *x;
+
+	for (i = o->ob_size; --i >= 0; ) {
+		x = o->ob_item[i];
+		if (x != NULL) {
+			err = visit(x, arg);
+			if (err)
+				return err;
+		}
+	}
+	return 0;
+}
+
 static PySequenceMethods tuple_as_sequence = {
 	(inquiry)tuplelength, /*sq_length*/
 	(binaryfunc)tupleconcat, /*sq_concat*/
@@ -453,6 +470,8 @@
 	0,		/*tp_setattro*/
 	0,		/*tp_as_buffer*/
 	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+	0,              /*tp_doc*/
+ 	(traverseproc)tupletraverse,	/* tp_traverse */
 };
 
 /* The following function breaks the notion that tuples are immutable: