]> granicus.if.org Git - python/commitdiff
Round 1 of Neil Schemenauer's GC patches:
authorJeremy Hylton <jeremy@alum.mit.edu>
Fri, 23 Jun 2000 14:18:11 +0000 (14:18 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Fri, 23 Jun 2000 14:18:11 +0000 (14:18 +0000)
This patch adds the type methods traverse and clear necessary for GC
implementation.

Include/object.h
Objects/classobject.c
Objects/dictobject.c
Objects/funcobject.c
Objects/listobject.c
Objects/tupleobject.c

index f6ceba5cbf25c4af8d011cddfab322a5fefcf6ba..e18e0e80fd20b5b9201572580f3883bd52a77cf8 100644 (file)
@@ -145,6 +145,8 @@ typedef int (*getwritebufferproc) Py_PROTO((PyObject *, int, void **));
 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 @@ typedef struct _typeobject {
 
        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;
 
index bd95bc039face1ca95059fb7b1f8a4d03e819c35..18908f3aceff4876b4f638e0c7dbf5e692b108c9 100644 (file)
@@ -387,6 +387,43 @@ class_str(op)
        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 @@ PyTypeObject PyClass_Type = {
        (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 @@ instance_hash(inst)
        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 @@ PyTypeObject PyInstance_Type = {
        (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 @@ instancemethod_hash(a)
        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 @@ PyTypeObject PyMethod_Type = {
        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 */
index 6e7fa3d0ef6172bee4a68d68f5204b65d3064ff4..2d33b927da9f6593e0e47841549824921e2e1474 100644 (file)
@@ -1038,6 +1038,31 @@ dict_clear(mp, args)
        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 @@ PyTypeObject PyDict_Type = {
        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 */
index a5e15cc9057ace7c1fe19d4ee9eb021a0cb66a69..142c7e7df9c5b46ea0b11f9accadf640fa0084c0 100644 (file)
@@ -239,6 +239,38 @@ func_hash(f)
        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 @@ PyTypeObject PyFunction_Type = {
        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 */
 };
index 163ba2a8194c48c59f981af00540468c89af5beb..65dfb18f7bb8bccd19be73e701f47ff3b4bd6543 100644 (file)
@@ -1418,6 +1418,30 @@ listremove(self, args)
        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 @@ PyTypeObject PyList_Type = {
        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 @@ static PyTypeObject immutable_list_type = {
        0,              /*tp_setattro*/
        0,              /*tp_as_buffer*/
        Py_TPFLAGS_DEFAULT,     /*tp_flags*/
+       0,              /* tp_doc */
+       (traverseproc)list_traverse,    /* tp_traverse */
 };
 
index f89fa365a9008634467cb71fb5ced82d75c2c223..bbb56b1adc4829433c0dbe946f96bebf0a372d20 100644 (file)
@@ -420,6 +420,23 @@ tuplerepeat(a, n)
        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 @@ PyTypeObject PyTuple_Type = {
        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: