[Patches] GC infrastructure patch 1 (tp_recurse, tp_clear)

Neil Schemenauer nascheme@enme.ucalgary.ca
Wed, 14 Jun 2000 12:38:18 -0600


--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

This patch adds the type methods recurse and clear necessary for
my GC patch.  It is straightforward so hopefully it can be
applied right away.

    Neil

--4Ckj6UjgE2iN1+kY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="recurse.diff"

Index: 0.9/Include/object.h
*** 0.9/Include/object.h Tue, 25 Apr 2000 17:33:19 -0600 nas (python/o/18_object.h 1.1 644)
--- 0.9(w)/Include/object.h Wed, 14 Jun 2000 12:26:41 -0600 nas (python/o/18_object.h 1.1 644)
***************
*** 145,150 ****
--- 145,152 ----
  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 (*recurseproc) Py_PROTO((PyObject *, visitproc, void *));
  
  typedef struct {
  	binaryfunc nb_add;
***************
*** 243,251 ****
  
  	char *tp_doc; /* Documentation string */
  
  	/* More spares */
- 	long tp_xxx5;
- 	long tp_xxx6;
  	long tp_xxx7;
  	long tp_xxx8;
  
--- 245,257 ----
  
  	char *tp_doc; /* Documentation string */
  
+ 	/* call function for all accessible objects */
+ 	recurseproc tp_recurse;
+ 	
+ 	/* delete references to contained objects */
+ 	inquiry tp_clear;
+ 
  	/* More spares */
  	long tp_xxx7;
  	long tp_xxx8;
  
Index: 0.9/Objects/classobject.c
*** 0.9/Objects/classobject.c Mon, 08 May 2000 12:24:03 -0600 nas (python/E/16_classobjec 1.1.2.2 644)
--- 0.9(w)/Objects/classobject.c Wed, 14 Jun 2000 12:27:59 -0600 nas (python/E/16_classobjec 1.1.2.2 644)
***************
*** 387,392 ****
--- 387,404 ----
  	return res;
  }
  
+ static int
+ class_recurse(PyClassObject *o, visitproc visit, void *closure)
+ {
+ 	if (o->cl_bases) visit(o->cl_bases, closure);
+ 	if (o->cl_dict) visit(o->cl_dict, closure);
+ 	if (o->cl_name) visit(o->cl_name, closure);
+ 	if (o->cl_getattr) visit(o->cl_getattr, closure);
+ 	if (o->cl_setattr) visit(o->cl_setattr, closure);
+ 	if (o->cl_delattr) visit(o->cl_delattr, closure);
+ 	return 1;
+ }
+ 
  PyTypeObject PyClass_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
  	0,
***************
*** 407,412 ****
--- 419,428 ----
  	(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 */
+ 	(recurseproc)class_recurse,	/* tp_recurse */
  };
  
  int
***************
*** 849,854 ****
--- 865,878 ----
  	return outcome;
  }
  
+ static int
+ instance_recurse(PyInstanceObject *o, visitproc visit, void *closure)
+ {
+ 	if (o->in_class) visit((PyObject *)(o->in_class), closure);
+ 	if (o->in_dict) visit(o->in_dict, closure);
+ 	return 1;
+ }
+ 
  static PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr;
  
  static int
***************
*** 1472,1478 ****
  	(getattrofunc)instance_getattr, /*tp_getattro*/
  	(setattrofunc)instance_setattr, /*tp_setattro*/
          0, /* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT, /*tp_flags */
  };
  
  
--- 1496,1504 ----
  	(getattrofunc)instance_getattr, /*tp_getattro*/
  	(setattrofunc)instance_setattr, /*tp_setattro*/
          0, /* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT, /*tp_flags*/
! 	0,		/* tp_doc */
! 	(recurseproc)instance_recurse,	/* tp_recurse */
  };
  
  
***************
*** 1662,1667 ****
--- 1688,1702 ----
  	return x ^ y;
  }
  
+ static int
+ instancemethod_recurse(PyMethodObject *im, visitproc visit, void *closure)
+ {
+ 	if (im->im_func) visit(im->im_func, closure);
+ 	if (im->im_self) visit(im->im_self, closure);
+ 	if (im->im_class) visit(im->im_class, closure);
+ 	return 1;
+ }
+ 
  PyTypeObject PyMethod_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
  	0,
***************
*** 1682,1687 ****
--- 1717,1726 ----
  	0,			/*tp_str*/
  	(getattrofunc)instancemethod_getattr, /*tp_getattro*/
  	0,			/*tp_setattro*/
+ 	0,			/* tp_as_buffer */
+ 	Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 	0,			/* tp_doc */
+ 	(recurseproc)instancemethod_recurse,	/* tp_recurse */
  };
  
  /* Clear out the free list */
Index: 0.9/Objects/dictobject.c
*** 0.9/Objects/dictobject.c Mon, 08 May 2000 12:24:03 -0600 nas (python/E/19_dictobject 1.1.2.1 644)
--- 0.9(w)/Objects/dictobject.c Wed, 14 Jun 2000 12:28:08 -0600 nas (python/E/19_dictobject 1.1.2.1 644)
***************
*** 1038,1043 ****
--- 1038,1068 ----
  	return Py_None;
  }
  
+ static int
+ dict_recurse(PyObject *op, visitproc visit, void *closure)
+ {
+ 	int i = 0;
+ 	PyObject *pk;
+ 	PyObject *pv;
+ 
+ 	while (PyDict_Next(op, &i, &pk, &pv)) {
+ 		if (!visit(pk, closure)) {
+ 			return 0;
+ 		}
+ 		if (!visit(pv, closure)) {
+ 			return 0;
+ 		}
+ 	}
+ 	return 1;
+ }
+ 
+ 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,1078 ****
--- 1098,1113 ----
  	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 */
+ 	(recurseproc)dict_recurse,	/* tp_recurse */
+ 	(inquiry)dict_tp_clear,		/* tp_clear */
  };
  
  /* For backward compatibility with old dictionary interface */
Index: 0.9/Objects/funcobject.c
*** 0.9/Objects/funcobject.c Mon, 08 May 2000 12:24:03 -0600 nas (python/E/23_funcobject 1.1.2.2 644)
--- 0.9(w)/Objects/funcobject.c Wed, 14 Jun 2000 12:28:19 -0600 nas (python/E/23_funcobject 1.1.2.2 644)
***************
*** 239,244 ****
--- 239,255 ----
  	return h;
  }
  
+ static int
+ func_recurse(PyFunctionObject *f, visitproc visit, void *closure)
+ {
+ 	if (f->func_code) visit(f->func_code, closure);
+ 	if (f->func_globals) visit(f->func_globals, closure);
+ 	if (f->func_defaults) visit(f->func_defaults, closure);
+ 	if (f->func_doc) visit(f->func_doc, closure);
+ 	if (f->func_name) visit(f->func_name, closure);
+ 	return 1;
+ }
+ 
  PyTypeObject PyFunction_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
  	0,
***************
*** 255,258 ****
--- 266,277 ----
  	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 */
+ 	(recurseproc)func_recurse,	/* tp_recurse */
  };
Index: 0.9/Objects/listobject.c
*** 0.9/Objects/listobject.c Mon, 05 Jun 2000 00:51:28 -0600 nas (python/E/25_listobject 1.1.2.3 644)
--- 0.9(w)/Objects/listobject.c Wed, 14 Jun 2000 12:28:32 -0600 nas (python/E/25_listobject 1.1.2.3 644)
***************
*** 1423,1428 ****
--- 1423,1449 ----
  	return NULL;
  }
  
+ static int
+ list_recurse(PyListObject *o, visitproc visit, void *closure)
+ {
+ 	int i;
+ 	PyObject *x;
+ 
+ 	for (i = o->ob_size; --i >= 0; ) {
+ 		x = o->ob_item[i];
+ 		if (x != NULL && !visit(x, closure))
+ 			return 0;
+ 	}
+ 	return 1;
+ }
+ 
+ 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[] =
***************
*** 1489,1494 ****
--- 1510,1525 ----
  	0,		/*tp_as_number*/
  	&list_as_sequence,	/*tp_as_sequence*/
  	0,		/*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 */
+ 	(recurseproc)list_recurse,	/* tp_recurse */
+ 	(inquiry)list_clear,	/* tp_clear */
  };
  
  
***************
*** 1557,1561 ****
--- 1588,1601 ----
  	0,		/*tp_as_number*/
  	&immutable_list_as_sequence,	/*tp_as_sequence*/
  	0,		/*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 */
+ 	(recurseproc)list_recurse,	/* tp_recurse */
  };
  
Index: 0.9/Objects/tupleobject.c
*** 0.9/Objects/tupleobject.c Mon, 05 Jun 2000 00:51:28 -0600 nas (python/E/33_tupleobjec 1.1.2.3 644)
--- 0.9(w)/Objects/tupleobject.c Wed, 14 Jun 2000 12:28:40 -0600 nas (python/E/33_tupleobjec 1.1.2.3 644)
***************
*** 420,425 ****
--- 420,439 ----
  	return (PyObject *) np;
  }
  
+ static int
+ tuplerecurse(PyTupleObject *o, visitproc visit, void *closure)
+ {
+ 	int i;
+ 	PyObject *x;
+ 
+ 	for (i = o->ob_size; --i >= 0; ) {
+ 		x = o->ob_item[i];
+ 		if (x != NULL && !visit(x, closure))
+ 			return 0;
+ 	}
+ 	return 1;
+ }
+ 
  static PySequenceMethods tuple_as_sequence = {
  	(inquiry)tuplelength, /*sq_length*/
  	(binaryfunc)tupleconcat, /*sq_concat*/
***************
*** 447,452 ****
--- 461,474 ----
  	&tuple_as_sequence,	/*tp_as_sequence*/
  	0,		/*tp_as_mapping*/
  	(hashfunc)tuplehash, /*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 */
+ 	(recurseproc)tuplerecurse,	/* tp_recurse */
  };
  
  /* The following function breaks the notion that tuples are immutable:

--4Ckj6UjgE2iN1+kY--