final patches from Neil Schemenauer for garbage collection
diff --git a/Objects/classobject.c b/Objects/classobject.c
index f1dabfe..4653d27 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -132,6 +132,7 @@
 	Py_XINCREF(op->cl_getattr);
 	Py_XINCREF(op->cl_setattr);
 	Py_XINCREF(op->cl_delattr);
+	PyObject_GC_Init(op);
 	return (PyObject *) op;
 }
 
@@ -141,6 +142,7 @@
 class_dealloc(op)
 	PyClassObject *op;
 {
+	PyObject_GC_Fini(op);
 	Py_DECREF(op->cl_bases);
 	Py_DECREF(op->cl_dict);
 	Py_XDECREF(op->cl_name);
@@ -428,7 +430,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"class",
-	sizeof(PyClassObject) + PyGC_INFO_SIZE,
+	sizeof(PyClassObject) + PyGC_HEAD_SIZE,
 	0,
 	(destructor)class_dealloc, /*tp_dealloc*/
 	0,		/*tp_print*/
@@ -490,6 +492,7 @@
 	if (inst == NULL)
 		return NULL;
 	inst->in_dict = PyDict_New();
+	PyObject_GC_Init(inst);
 	if (inst->in_dict == NULL) {
 		PyObject_DEL(inst);
 		return NULL;
@@ -539,11 +542,12 @@
 	PyObject *error_type, *error_value, *error_traceback;
 	PyObject *del;
 	static PyObject *delstr;
+	extern long _Py_RefTotal;
+	PyObject_GC_Fini(inst);
 	/* Call the __del__ method if it exists.  First temporarily
 	   revive the object and save the current exception, if any. */
 #ifdef Py_TRACE_REFS
 	/* much too complicated if Py_TRACE_REFS defined */
-	extern long _Py_RefTotal;
 	inst->ob_type = &PyInstance_Type;
 	_Py_NewReference((PyObject *)inst);
 	_Py_RefTotal--;		/* compensate for increment in NEWREF */
@@ -591,6 +595,7 @@
 #ifdef COUNT_ALLOCS
 		inst->ob_type->tp_free--;
 #endif
+		PyObject_GC_Init((PyObject *)inst);
 		return; /* __del__ added a reference; don't delete now */
 	}
 #ifdef Py_TRACE_REFS
@@ -598,7 +603,9 @@
 	inst->ob_type->tp_free--;	/* compensate for increment in UNREF */
 #endif
 	_Py_ForgetReference((PyObject *)inst);
+#ifndef WITH_CYCLE_GC
 	inst->ob_type = NULL;
+#endif
 #endif /* Py_TRACE_REFS */
 	Py_DECREF(inst->in_class);
 	Py_XDECREF(inst->in_dict);
@@ -1510,7 +1517,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"instance",
-	sizeof(PyInstanceObject) + PyGC_INFO_SIZE,
+	sizeof(PyInstanceObject) + PyGC_HEAD_SIZE,
 	0,
 	(destructor)instance_dealloc, /*tp_dealloc*/
 	0,			/*tp_print*/
@@ -1568,6 +1575,7 @@
 	im->im_self = self;
 	Py_INCREF(class);
 	im->im_class = class;
+	PyObject_GC_Init(im);
 	return (PyObject *)im;
 }
 
@@ -1643,6 +1651,7 @@
 instancemethod_dealloc(im)
 	register PyMethodObject *im;
 {
+	PyObject_GC_Fini(im);
 	Py_DECREF(im->im_func);
 	Py_XDECREF(im->im_self);
 	Py_DECREF(im->im_class);
@@ -1745,7 +1754,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"instance method",
-	sizeof(PyMethodObject) + PyGC_INFO_SIZE,
+	sizeof(PyMethodObject) + PyGC_HEAD_SIZE,
 	0,
 	(destructor)instancemethod_dealloc, /*tp_dealloc*/
 	0,			/*tp_print*/
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index ce38f11..ea3af48 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -129,6 +129,7 @@
 	mp->ma_table = NULL;
 	mp->ma_fill = 0;
 	mp->ma_used = 0;
+	PyObject_GC_Init(mp);
 	return (PyObject *)mp;
 }
 
@@ -481,6 +482,7 @@
 	register int i;
 	register dictentry *ep;
 	Py_TRASHCAN_SAFE_BEGIN(mp)
+	PyObject_GC_Fini(mp);
 	for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
 		if (ep->me_key != NULL) {
 			Py_DECREF(ep->me_key);
@@ -1087,7 +1089,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"dictionary",
-	sizeof(dictobject) + PyGC_INFO_SIZE,
+	sizeof(dictobject) + PyGC_HEAD_SIZE,
 	0,
 	(destructor)dict_dealloc, /*tp_dealloc*/
 	(printfunc)dict_print, /*tp_print*/
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index d9ce027..2736d65 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -63,6 +63,7 @@
 		Py_INCREF(doc);
 		op->func_doc = doc;
 	}
+	PyObject_GC_Init(op);
 	return (PyObject *)op;
 }
 
@@ -186,6 +187,7 @@
 func_dealloc(op)
 	PyFunctionObject *op;
 {
+	PyObject_GC_Fini(op);
 	Py_DECREF(op->func_code);
 	Py_DECREF(op->func_globals);
 	Py_DECREF(op->func_name);
@@ -277,7 +279,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"function",
-	sizeof(PyFunctionObject) + PyGC_INFO_SIZE,
+	sizeof(PyFunctionObject) + PyGC_HEAD_SIZE,
 	0,
 	(destructor)func_dealloc, /*tp_dealloc*/
 	0,		/*tp_print*/
diff --git a/Objects/listobject.c b/Objects/listobject.c
index e9f12ab..a75100e 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -72,10 +72,11 @@
 	}
 	/* PyObject_NewVar is inlined */
 	op = (PyListObject *) PyObject_MALLOC(sizeof(PyListObject)
-						+ PyGC_INFO_SIZE);
+						+ PyGC_HEAD_SIZE);
 	if (op == NULL) {
 		return PyErr_NoMemory();
 	}
+	op = (PyListObject *) PyObject_FROM_GC(op);
 	if (size <= 0) {
 		op->ob_item = NULL;
 	}
@@ -89,6 +90,7 @@
 	PyObject_INIT_VAR(op, &PyList_Type, size);
 	for (i = 0; i < size; i++)
 		op->ob_item[i] = NULL;
+	PyObject_GC_Init(op);
 	return (PyObject *) op;
 }
 
@@ -216,6 +218,7 @@
 {
 	int i;
 	Py_TRASHCAN_SAFE_BEGIN(op)
+	PyObject_GC_Fini(op);
 	if (op->ob_item != NULL) {
 		/* Do it backwards, for Christian Tismer.
 		   There's a simple test case where somehow this reduces
@@ -1498,7 +1501,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"list",
-	sizeof(PyListObject) + PyGC_INFO_SIZE,
+	sizeof(PyListObject) + PyGC_HEAD_SIZE,
 	0,
 	(destructor)list_dealloc, /*tp_dealloc*/
 	(printfunc)list_print, /*tp_print*/
@@ -1577,7 +1580,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"list (immutable, during sort)",
-	sizeof(PyListObject) + PyGC_INFO_SIZE,
+	sizeof(PyListObject) + PyGC_HEAD_SIZE,
 	0,
 	0,		/*tp_dealloc*/ /* Cannot happen */
 	(printfunc)list_print, /*tp_print*/
diff --git a/Objects/object.c b/Objects/object.c
index 9ed03b2..6eaff67 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -124,6 +124,10 @@
 				"NULL object passed to PyObject_Init");
 		return op;
   	}
+#ifdef WITH_CYCLE_GC
+	if (PyType_IS_GC(tp))
+		op = (PyObject *) PyObject_FROM_GC(op);
+#endif
 	/* Any changes should be reflected in PyObject_INIT (objimpl.h) */
 	op->ob_type = tp;
 	_Py_NewReference(op);
@@ -141,6 +145,10 @@
 				"NULL object passed to PyObject_InitVar");
 		return op;
 	}
+#ifdef WITH_CYCLE_GC
+	if (PyType_IS_GC(tp))
+		op = (PyVarObject *) PyObject_FROM_GC(op);
+#endif
 	/* Any changes should be reflected in PyObject_INIT_VAR */
 	op->ob_size = size;
 	op->ob_type = tp;
@@ -156,6 +164,10 @@
 	op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
 	if (op == NULL)
 		return PyErr_NoMemory();
+#ifdef WITH_CYCLE_GC
+	if (PyType_IS_GC(tp))
+		op = (PyObject *) PyObject_FROM_GC(op);
+#endif
 	return PyObject_INIT(op, tp);
 }
 
@@ -168,6 +180,10 @@
 	op = (PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE(tp, size));
 	if (op == NULL)
 		return (PyVarObject *)PyErr_NoMemory();
+#ifdef WITH_CYCLE_GC
+	if (PyType_IS_GC(tp))
+		op = (PyVarObject *) PyObject_FROM_GC(op);
+#endif
 	return PyObject_INIT_VAR(op, tp, size);
 }
 
@@ -175,9 +191,23 @@
 _PyObject_Del(op)
 	PyObject *op;
 {
-	PyObject_FREE(op);
+#ifdef WITH_CYCLE_GC
+	if (PyType_IS_GC(op->ob_type)) {
+		PyGC_Head *g = PyObject_AS_GC(op);
+		PyObject_FREE(g);
+	} else
+#endif
+	{
+		PyObject_FREE(op);
+	}
 }
 
+#ifndef WITH_CYCLE_GC
+/* extension modules might need these */
+void _PyGC_Insert(PyObject *op) { }
+void _PyGC_Remove(PyObject *op) { }
+#endif
+
 int
 PyObject_Print(op, fp, flags)
 	PyObject *op;
@@ -917,8 +947,10 @@
 {
 	destructor dealloc = op->ob_type->tp_dealloc;
 	_Py_ForgetReference(op);
+#ifndef WITH_CYCLE_GC
 	if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL-1)
 		op->ob_type = NULL;
+#endif
 	(*dealloc)(op);
 }
 
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 73e3304..46e67a8 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -94,7 +94,7 @@
 		/* Check for overflow */
 		if (nbytes / sizeof(PyObject *) != (size_t)size ||
 		    (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *)
-		     		+ PyGC_INFO_SIZE)
+		     		+ PyGC_HEAD_SIZE)
 		    <= 0)
 		{
 			return PyErr_NoMemory();
@@ -103,7 +103,7 @@
 		op = (PyTupleObject *) PyObject_MALLOC(nbytes);
 		if (op == NULL)
 			return PyErr_NoMemory();
-
+		op = (PyTupleObject *) PyObject_FROM_GC(op);
 		PyObject_INIT_VAR(op, &PyTuple_Type, size);
 	}
 	for (i = 0; i < size; i++)
@@ -115,6 +115,7 @@
 		Py_INCREF(op);	/* extra INCREF so that this is never freed */
 	}
 #endif
+	PyObject_GC_Init(op);
 	return (PyObject *) op;
 }
 
@@ -181,6 +182,7 @@
 	register int i;
 	register int len =  op->ob_size;
 	Py_TRASHCAN_SAFE_BEGIN(op)
+	PyObject_GC_Fini(op);
 	if (len > 0) {
 		i = len;
 		while (--i >= 0)
@@ -453,7 +455,7 @@
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,
 	"tuple",
-	sizeof(PyTupleObject) - sizeof(PyObject *) + PyGC_INFO_SIZE,
+	sizeof(PyTupleObject) - sizeof(PyObject *) + PyGC_HEAD_SIZE,
 	sizeof(PyObject *),
 	(destructor)tupledealloc, /*tp_dealloc*/
 	(printfunc)tupleprint, /*tp_print*/
@@ -557,12 +559,27 @@
 	} else 
 #endif		
 	{
+#ifdef WITH_CYCLE_GC
+		PyGC_Head *g = PyObject_AS_GC((PyObject *)v);
+		PyObject_GC_Fini((PyObject *)v);
+		sv = (PyTupleObject *)
+			PyObject_REALLOC((char *)g, sizeof(PyTupleObject) 
+					+ PyGC_HEAD_SIZE
+					+ newsize * sizeof(PyObject *));
+		if (g == NULL) {
+			sv = NULL;
+		} else {
+			sv = (PyTupleObject *)PyObject_FROM_GC(g);
+		}
+#else
 		sv = (PyTupleObject *)
 			PyObject_REALLOC((char *)v, sizeof(PyTupleObject) 
-					+ PyGC_INFO_SIZE
+					+ PyGC_HEAD_SIZE
 					+ newsize * sizeof(PyObject *));
+#endif
 		*pv = (PyObject *) sv;
 		if (sv == NULL) {
+			PyObject_GC_Init((PyObject *)v);
 			PyObject_DEL(v);
 			PyErr_NoMemory();
 			return -1;
@@ -578,6 +595,7 @@
 			sv->ob_item[i - sizediff] = NULL;
 		}
 	}
+	PyObject_GC_Init(sv);
 	sv->ob_size = newsize;
 	return 0;
 }