mirror of https://github.com/python/cpython
Round 1 of Neil Schemenauer's GC patches:
This patch adds the type methods traverse and clear necessary for GC implementation.
This commit is contained in:
parent
a392dcb211
commit
8caad49c30
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue