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 (*getsegcountproc) Py_PROTO((PyObject *, int *));
|
||||||
typedef int (*getcharbufferproc) Py_PROTO((PyObject *, int, const char **));
|
typedef int (*getcharbufferproc) Py_PROTO((PyObject *, int, const char **));
|
||||||
typedef int (*objobjproc) Py_PROTO((PyObject *, PyObject *));
|
typedef int (*objobjproc) Py_PROTO((PyObject *, PyObject *));
|
||||||
|
typedef int (*visitproc) Py_PROTO((PyObject *, void *));
|
||||||
|
typedef int (*traverseproc) Py_PROTO((PyObject *, visitproc, void *));
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
binaryfunc nb_add;
|
binaryfunc nb_add;
|
||||||
|
@ -243,9 +245,13 @@ typedef struct _typeobject {
|
||||||
|
|
||||||
char *tp_doc; /* Documentation string */
|
char *tp_doc; /* Documentation string */
|
||||||
|
|
||||||
|
/* call function for all accessible objects */
|
||||||
|
traverseproc tp_traverse;
|
||||||
|
|
||||||
|
/* delete references to contained objects */
|
||||||
|
inquiry tp_clear;
|
||||||
|
|
||||||
/* More spares */
|
/* More spares */
|
||||||
long tp_xxx5;
|
|
||||||
long tp_xxx6;
|
|
||||||
long tp_xxx7;
|
long tp_xxx7;
|
||||||
long tp_xxx8;
|
long tp_xxx8;
|
||||||
|
|
||||||
|
|
|
@ -387,6 +387,43 @@ class_str(op)
|
||||||
return res;
|
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 = {
|
PyTypeObject PyClass_Type = {
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
PyObject_HEAD_INIT(&PyType_Type)
|
||||||
0,
|
0,
|
||||||
|
@ -407,6 +444,10 @@ PyTypeObject PyClass_Type = {
|
||||||
(reprfunc)class_str, /*tp_str*/
|
(reprfunc)class_str, /*tp_str*/
|
||||||
(getattrofunc)class_getattr, /*tp_getattro*/
|
(getattrofunc)class_getattr, /*tp_getattro*/
|
||||||
(setattrofunc)class_setattr, /*tp_setattro*/
|
(setattrofunc)class_setattr, /*tp_setattro*/
|
||||||
|
0, /* tp_as_buffer */
|
||||||
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||||
|
0, /* tp_doc */
|
||||||
|
(traverseproc)class_traverse, /* tp_traverse */
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -849,6 +890,23 @@ instance_hash(inst)
|
||||||
return outcome;
|
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 PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1472,7 +1530,9 @@ PyTypeObject PyInstance_Type = {
|
||||||
(getattrofunc)instance_getattr, /*tp_getattro*/
|
(getattrofunc)instance_getattr, /*tp_getattro*/
|
||||||
(setattrofunc)instance_setattr, /*tp_setattro*/
|
(setattrofunc)instance_setattr, /*tp_setattro*/
|
||||||
0, /* tp_as_buffer */
|
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;
|
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 = {
|
PyTypeObject PyMethod_Type = {
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
PyObject_HEAD_INIT(&PyType_Type)
|
||||||
0,
|
0,
|
||||||
|
@ -1682,6 +1764,10 @@ PyTypeObject PyMethod_Type = {
|
||||||
0, /*tp_str*/
|
0, /*tp_str*/
|
||||||
(getattrofunc)instancemethod_getattr, /*tp_getattro*/
|
(getattrofunc)instancemethod_getattr, /*tp_getattro*/
|
||||||
0, /*tp_setattro*/
|
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 */
|
/* Clear out the free list */
|
||||||
|
|
|
@ -1038,6 +1038,31 @@ dict_clear(mp, args)
|
||||||
return Py_None;
|
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[] = {
|
static PyMethodDef mapp_methods[] = {
|
||||||
{"has_key", (PyCFunction)dict_has_key, METH_VARARGS},
|
{"has_key", (PyCFunction)dict_has_key, METH_VARARGS},
|
||||||
{"keys", (PyCFunction)dict_keys},
|
{"keys", (PyCFunction)dict_keys},
|
||||||
|
@ -1073,6 +1098,16 @@ PyTypeObject PyDict_Type = {
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
&dict_as_mapping, /*tp_as_mapping*/
|
&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 */
|
/* For backward compatibility with old dictionary interface */
|
||||||
|
|
|
@ -239,6 +239,38 @@ func_hash(f)
|
||||||
return h;
|
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 = {
|
PyTypeObject PyFunction_Type = {
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
PyObject_HEAD_INIT(&PyType_Type)
|
||||||
0,
|
0,
|
||||||
|
@ -255,4 +287,12 @@ PyTypeObject PyFunction_Type = {
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
(hashfunc)func_hash, /*tp_hash*/
|
(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;
|
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[] =
|
static char append_doc[] =
|
||||||
"L.append(object) -- append object to end";
|
"L.append(object) -- append object to end";
|
||||||
static char extend_doc[] =
|
static char extend_doc[] =
|
||||||
|
@ -1491,6 +1515,9 @@ PyTypeObject PyList_Type = {
|
||||||
0, /*tp_setattro*/
|
0, /*tp_setattro*/
|
||||||
0, /*tp_as_buffer*/
|
0, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
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_setattro*/
|
||||||
0, /*tp_as_buffer*/
|
0, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||||
|
0, /* tp_doc */
|
||||||
|
(traverseproc)list_traverse, /* tp_traverse */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -420,6 +420,23 @@ tuplerepeat(a, n)
|
||||||
return (PyObject *) np;
|
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 = {
|
static PySequenceMethods tuple_as_sequence = {
|
||||||
(inquiry)tuplelength, /*sq_length*/
|
(inquiry)tuplelength, /*sq_length*/
|
||||||
(binaryfunc)tupleconcat, /*sq_concat*/
|
(binaryfunc)tupleconcat, /*sq_concat*/
|
||||||
|
@ -453,6 +470,8 @@ PyTypeObject PyTuple_Type = {
|
||||||
0, /*tp_setattro*/
|
0, /*tp_setattro*/
|
||||||
0, /*tp_as_buffer*/
|
0, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||||
|
0, /*tp_doc*/
|
||||||
|
(traverseproc)tupletraverse, /* tp_traverse */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The following function breaks the notion that tuples are immutable:
|
/* The following function breaks the notion that tuples are immutable:
|
||||||
|
|
Loading…
Reference in New Issue