Use Py_VISIT in all tp_traverse methods, instead of traversing manually or

using a custom, nearly-identical macro. This probably changes how some of
these functions are compiled, which may result in fractionally slower (or
faster) execution. Considering the nature of traversal, visiting much of the
address space in unpredictable patterns, I'd argue the code readability and
maintainability is well worth it ;P
This commit is contained in:
Thomas Wouters 2006-04-15 21:47:09 +00:00
parent 447d095976
commit c6e55068ca
20 changed files with 108 additions and 339 deletions

View file

@ -48,7 +48,16 @@ module instead.
} \ } \
} while (0) } while (0)
#endif #endif
#ifndef Py_VISIT
#define Py_VISIT(op) \
do { \
if (op) { \
int vret = visit((PyObject *)(op), arg); \
if (vret) \
return vret; \
} \
} while (0)
#endif
/* end 2.2 compatibility macros */ /* end 2.2 compatibility macros */
@ -825,16 +834,9 @@ Reader_dealloc(ReaderObj *self)
static int static int
Reader_traverse(ReaderObj *self, visitproc visit, void *arg) Reader_traverse(ReaderObj *self, visitproc visit, void *arg)
{ {
int err; Py_VISIT(self->dialect);
#define VISIT(SLOT) \ Py_VISIT(self->input_iter);
if (SLOT) { \ Py_VISIT(self->fields);
err = visit((PyObject *)(SLOT), arg); \
if (err) \
return err; \
}
VISIT(self->dialect);
VISIT(self->input_iter);
VISIT(self->fields);
return 0; return 0;
} }
@ -1255,15 +1257,8 @@ Writer_dealloc(WriterObj *self)
static int static int
Writer_traverse(WriterObj *self, visitproc visit, void *arg) Writer_traverse(WriterObj *self, visitproc visit, void *arg)
{ {
int err; Py_VISIT(self->dialect);
#define VISIT(SLOT) \ Py_VISIT(self->writeline);
if (SLOT) { \
err = visit((PyObject *)(SLOT), arg); \
if (err) \
return err; \
}
VISIT(self->dialect);
VISIT(self->writeline);
return 0; return 0;
} }

View file

@ -2061,8 +2061,7 @@ arrayiter_dealloc(arrayiterobject *it)
static int static int
arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg) arrayiter_traverse(arrayiterobject *it, visitproc visit, void *arg)
{ {
if (it->ao != NULL) Py_VISIT(it->ao);
return visit((PyObject *)(it->ao), arg);
return 0; return 0;
} }

View file

@ -2909,22 +2909,14 @@ Pickler_dealloc(Picklerobject *self)
static int static int
Pickler_traverse(Picklerobject *self, visitproc visit, void *arg) Pickler_traverse(Picklerobject *self, visitproc visit, void *arg)
{ {
int err; Py_VISIT(self->write);
#define VISIT(SLOT) \ Py_VISIT(self->memo);
if (SLOT) { \ Py_VISIT(self->fast_memo);
err = visit((PyObject *)(SLOT), arg); \ Py_VISIT(self->arg);
if (err) \ Py_VISIT(self->file);
return err; \ Py_VISIT(self->pers_func);
} Py_VISIT(self->inst_pers_func);
VISIT(self->write); Py_VISIT(self->dispatch_table);
VISIT(self->memo);
VISIT(self->fast_memo);
VISIT(self->arg);
VISIT(self->file);
VISIT(self->pers_func);
VISIT(self->inst_pers_func);
VISIT(self->dispatch_table);
#undef VISIT
return 0; return 0;
} }
@ -5258,24 +5250,15 @@ Unpickler_dealloc(Unpicklerobject *self)
static int static int
Unpickler_traverse(Unpicklerobject *self, visitproc visit, void *arg) Unpickler_traverse(Unpicklerobject *self, visitproc visit, void *arg)
{ {
int err; Py_VISIT(self->readline);
Py_VISIT(self->read);
#define VISIT(SLOT) \ Py_VISIT(self->file);
if (SLOT) { \ Py_VISIT(self->memo);
err = visit((PyObject *)(SLOT), arg); \ Py_VISIT(self->stack);
if (err) \ Py_VISIT(self->pers_func);
return err; \ Py_VISIT(self->arg);
} Py_VISIT(self->last_string);
VISIT(self->readline); Py_VISIT(self->find_class);
VISIT(self->read);
VISIT(self->file);
VISIT(self->memo);
VISIT(self->stack);
VISIT(self->pers_func);
VISIT(self->arg);
VISIT(self->last_string);
VISIT(self->find_class);
#undef VISIT
return 0; return 0;
} }

View file

@ -358,8 +358,7 @@ itemgetter_dealloc(itemgetterobject *ig)
static int static int
itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg) itemgetter_traverse(itemgetterobject *ig, visitproc visit, void *arg)
{ {
if (ig->item) Py_VISIT(ig->item);
return visit(ig->item, arg);
return 0; return 0;
} }
@ -497,8 +496,7 @@ attrgetter_dealloc(attrgetterobject *ag)
static int static int
attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg) attrgetter_traverse(attrgetterobject *ag, visitproc visit, void *arg)
{ {
if (ag->attr) Py_VISIT(ag->attr);
return visit(ag->attr, arg);
return 0; return 0;
} }

View file

@ -1655,13 +1655,8 @@ static int
xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
{ {
int i, err; int i, err;
for (i = 0; handler_info[i].name != NULL; i++) { for (i = 0; handler_info[i].name != NULL; i++)
if (!op->handlers[i]) Py_VISIT(op->handlers[i]);
continue;
err = visit(op->handlers[i], arg);
if (err)
return err;
}
return 0; return 0;
} }

View file

@ -170,13 +170,7 @@ static int
zipimporter_traverse(PyObject *obj, visitproc visit, void *arg) zipimporter_traverse(PyObject *obj, visitproc visit, void *arg)
{ {
ZipImporter *self = (ZipImporter *)obj; ZipImporter *self = (ZipImporter *)obj;
int err; Py_VISIT(self->files);
if (self->files != NULL) {
err = visit(self->files, arg);
if (err)
return err;
}
return 0; return 0;
} }

View file

@ -73,8 +73,7 @@ cell_repr(PyCellObject *op)
static int static int
cell_traverse(PyCellObject *op, visitproc visit, void *arg) cell_traverse(PyCellObject *op, visitproc visit, void *arg)
{ {
if (op->ob_ref) Py_VISIT(op->ob_ref);
return visit(op->ob_ref, arg);
return 0; return 0;
} }

View file

@ -404,37 +404,12 @@ class_str(PyClassObject *op)
static int static int
class_traverse(PyClassObject *o, visitproc visit, void *arg) class_traverse(PyClassObject *o, visitproc visit, void *arg)
{ {
int err; Py_VISIT(o->cl_bases);
if (o->cl_bases) { Py_VISIT(o->cl_dict);
err = visit(o->cl_bases, arg); Py_VISIT(o->cl_name);
if (err) Py_VISIT(o->cl_getattr);
return err; Py_VISIT(o->cl_setattr);
} Py_VISIT(o->cl_delattr);
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; return 0;
} }
@ -979,17 +954,8 @@ instance_hash(PyInstanceObject *inst)
static int static int
instance_traverse(PyInstanceObject *o, visitproc visit, void *arg) instance_traverse(PyInstanceObject *o, visitproc visit, void *arg)
{ {
int err; Py_VISIT(o->in_class);
if (o->in_class) { Py_VISIT(o->in_dict);
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 0; return 0;
} }
@ -2348,22 +2314,9 @@ instancemethod_hash(PyMethodObject *a)
static int static int
instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg) instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg)
{ {
int err; Py_VISIT(im->im_func);
if (im->im_func) { Py_VISIT(im->im_self);
err = visit(im->im_func, arg); Py_VISIT(im->im_class);
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 0; return 0;
} }

View file

@ -377,13 +377,7 @@ static int
descr_traverse(PyObject *self, visitproc visit, void *arg) descr_traverse(PyObject *self, visitproc visit, void *arg)
{ {
PyDescrObject *descr = (PyDescrObject *)self; PyDescrObject *descr = (PyDescrObject *)self;
int err; Py_VISIT(descr->d_type);
if (descr->d_type) {
err = visit((PyObject *)(descr->d_type), arg);
if (err)
return err;
}
return 0; return 0;
} }
@ -814,13 +808,7 @@ static int
proxy_traverse(PyObject *self, visitproc visit, void *arg) proxy_traverse(PyObject *self, visitproc visit, void *arg)
{ {
proxyobject *pp = (proxyobject *)self; proxyobject *pp = (proxyobject *)self;
int err; Py_VISIT(pp->dict);
if (pp->dict) {
err = visit(pp->dict, arg);
if (err)
return err;
}
return 0; return 0;
} }
@ -999,18 +987,8 @@ static int
wrapper_traverse(PyObject *self, visitproc visit, void *arg) wrapper_traverse(PyObject *self, visitproc visit, void *arg)
{ {
wrapperobject *wp = (wrapperobject *)self; wrapperobject *wp = (wrapperobject *)self;
int err; Py_VISIT(wp->descr);
Py_VISIT(wp->self);
if (wp->descr) {
err = visit((PyObject *)(wp->descr), arg);
if (err)
return err;
}
if (wp->self) {
err = visit(wp->self, arg);
if (err)
return err;
}
return 0; return 0;
} }
@ -1237,20 +1215,10 @@ static int
property_traverse(PyObject *self, visitproc visit, void *arg) property_traverse(PyObject *self, visitproc visit, void *arg)
{ {
propertyobject *pp = (propertyobject *)self; propertyobject *pp = (propertyobject *)self;
int err; Py_VISIT(pp->prop_get);
Py_VISIT(pp->prop_set);
#define VISIT(SLOT) \ Py_VISIT(pp->prop_del);
if (pp->SLOT) { \ Py_VISIT(pp->prop_doc);
err = visit((PyObject *)(pp->SLOT), arg); \
if (err) \
return err; \
}
VISIT(prop_get);
VISIT(prop_set);
VISIT(prop_del);
VISIT(prop_doc);
return 0; return 0;
} }

View file

@ -1732,17 +1732,12 @@ static int
dict_traverse(PyObject *op, visitproc visit, void *arg) dict_traverse(PyObject *op, visitproc visit, void *arg)
{ {
Py_ssize_t i = 0; Py_ssize_t i = 0;
int err;
PyObject *pk; PyObject *pk;
PyObject *pv; PyObject *pv;
while (PyDict_Next(op, &i, &pk, &pv)) { while (PyDict_Next(op, &i, &pk, &pv)) {
err = visit(pk, arg); Py_VISIT(pk);
if (err) Py_VISIT(pv);
return err;
err = visit(pv, arg);
if (err)
return err;
} }
return 0; return 0;
} }

View file

@ -49,18 +49,8 @@ enum_dealloc(enumobject *en)
static int static int
enum_traverse(enumobject *en, visitproc visit, void *arg) enum_traverse(enumobject *en, visitproc visit, void *arg)
{ {
int err; Py_VISIT(en->en_sit);
Py_VISIT(en->en_result);
if (en->en_sit) {
err = visit(en->en_sit, arg);
if (err)
return err;
}
if (en->en_result) {
err = visit(en->en_result, arg);
if (err)
return err;
}
return 0; return 0;
} }
@ -205,8 +195,7 @@ reversed_dealloc(reversedobject *ro)
static int static int
reversed_traverse(reversedobject *ro, visitproc visit, void *arg) reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
{ {
if (ro->seq) Py_VISIT(ro->seq);
return visit((PyObject *)(ro->seq), arg);
return 0; return 0;
} }

View file

@ -466,47 +466,14 @@ func_repr(PyFunctionObject *op)
static int static int
func_traverse(PyFunctionObject *f, visitproc visit, void *arg) func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
{ {
int err; Py_VISIT(f->func_code);
if (f->func_code) { Py_VISIT(f->func_globals);
err = visit(f->func_code, arg); Py_VISIT(f->func_module);
if (err) Py_VISIT(f->func_defaults);
return err; Py_VISIT(f->func_doc);
} Py_VISIT(f->func_name);
if (f->func_globals) { Py_VISIT(f->func_dict);
err = visit(f->func_globals, arg); Py_VISIT(f->func_closure);
if (err)
return err;
}
if (f->func_module) {
err = visit(f->func_module, 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;
}
if (f->func_dict) {
err = visit(f->func_dict, arg);
if (err)
return err;
}
if (f->func_closure) {
err = visit(f->func_closure, arg);
if (err)
return err;
}
return 0; return 0;
} }
@ -647,9 +614,8 @@ cm_dealloc(classmethod *cm)
static int static int
cm_traverse(classmethod *cm, visitproc visit, void *arg) cm_traverse(classmethod *cm, visitproc visit, void *arg)
{ {
if (!cm->cm_callable) Py_VISIT(cm->cm_callable);
return 0; return 0;
return visit(cm->cm_callable, arg);
} }
static int static int
@ -806,9 +772,8 @@ sm_dealloc(staticmethod *sm)
static int static int
sm_traverse(staticmethod *sm, visitproc visit, void *arg) sm_traverse(staticmethod *sm, visitproc visit, void *arg)
{ {
if (!sm->sm_callable) Py_VISIT(sm->sm_callable);
return 0; return 0;
return visit(sm->sm_callable, arg);
} }
static int static int

View file

@ -38,9 +38,8 @@ iter_dealloc(seqiterobject *it)
static int static int
iter_traverse(seqiterobject *it, visitproc visit, void *arg) iter_traverse(seqiterobject *it, visitproc visit, void *arg)
{ {
if (it->it_seq == NULL) Py_VISIT(it->it_seq);
return 0; return 0;
return visit(it->it_seq, arg);
} }
static PyObject * static PyObject *
@ -162,11 +161,8 @@ calliter_dealloc(calliterobject *it)
static int static int
calliter_traverse(calliterobject *it, visitproc visit, void *arg) calliter_traverse(calliterobject *it, visitproc visit, void *arg)
{ {
int err; Py_VISIT(it->it_callable);
if (it->it_callable != NULL && (err = visit(it->it_callable, arg))) Py_VISIT(it->it_sentinel);
return err;
if (it->it_sentinel != NULL && (err = visit(it->it_sentinel, arg)))
return err;
return 0; return 0;
} }

View file

@ -2276,14 +2276,8 @@ list_traverse(PyListObject *o, visitproc visit, void *arg)
Py_ssize_t i; Py_ssize_t i;
PyObject *x; PyObject *x;
for (i = o->ob_size; --i >= 0; ) { for (i = o->ob_size; --i >= 0; )
x = o->ob_item[i]; Py_VISIT(o->ob_item[i]);
if (x != NULL) {
int err = visit(x, arg);
if (err)
return err;
}
}
return 0; return 0;
} }
@ -2779,9 +2773,8 @@ listiter_dealloc(listiterobject *it)
static int static int
listiter_traverse(listiterobject *it, visitproc visit, void *arg) listiter_traverse(listiterobject *it, visitproc visit, void *arg)
{ {
if (it->it_seq == NULL) Py_VISIT(it->it_seq);
return 0; return 0;
return visit((PyObject *)it->it_seq, arg);
} }
static PyObject * static PyObject *
@ -2898,9 +2891,8 @@ listreviter_dealloc(listreviterobject *it)
static int static int
listreviter_traverse(listreviterobject *it, visitproc visit, void *arg) listreviter_traverse(listreviterobject *it, visitproc visit, void *arg)
{ {
if (it->it_seq == NULL) Py_VISIT(it->it_seq);
return 0; return 0;
return visit((PyObject *)it->it_seq, arg);
} }
static PyObject * static PyObject *

View file

@ -149,17 +149,8 @@ meth_get__name__(PyCFunctionObject *m, void *closure)
static int static int
meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
{ {
int err; Py_VISIT(m->m_self);
if (m->m_self != NULL) { Py_VISIT(m->m_module);
err = visit(m->m_self, arg);
if (err)
return err;
}
if (m->m_module != NULL) {
err = visit(m->m_module, arg);
if (err)
return err;
}
return 0; return 0;
} }

View file

@ -204,8 +204,7 @@ module_repr(PyModuleObject *m)
static int static int
module_traverse(PyModuleObject *m, visitproc visit, void *arg) module_traverse(PyModuleObject *m, visitproc visit, void *arg)
{ {
if (m->md_dict != NULL) Py_VISIT(m->md_dict);
return visit(m->md_dict, arg);
return 0; return 0;
} }

View file

@ -438,16 +438,9 @@ static int
tupletraverse(PyTupleObject *o, visitproc visit, void *arg) tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
{ {
Py_ssize_t i; Py_ssize_t i;
PyObject *x;
for (i = o->ob_size; --i >= 0; ) { for (i = o->ob_size; --i >= 0; )
x = o->ob_item[i]; Py_VISIT(o->ob_item[i]);
if (x != NULL) {
int err = visit(x, arg);
if (err)
return err;
}
}
return 0; return 0;
} }
@ -802,9 +795,8 @@ tupleiter_dealloc(tupleiterobject *it)
static int static int
tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg) tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)
{ {
if (it->it_seq == NULL) Py_VISIT(it->it_seq);
return 0; return 0;
return visit((PyObject *)it->it_seq, arg);
} }
static PyObject * static PyObject *

View file

@ -525,21 +525,15 @@ subtype_traverse(PyObject *self, visitproc visit, void *arg)
if (type->tp_dictoffset != base->tp_dictoffset) { if (type->tp_dictoffset != base->tp_dictoffset) {
PyObject **dictptr = _PyObject_GetDictPtr(self); PyObject **dictptr = _PyObject_GetDictPtr(self);
if (dictptr && *dictptr) { if (dictptr && *dictptr)
int err = visit(*dictptr, arg); Py_VISIT(*dictptr);
if (err)
return err;
}
} }
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) { if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
/* For a heaptype, the instances count as references /* For a heaptype, the instances count as references
to the type. Traverse the type so the collector to the type. Traverse the type so the collector
can find cycles involving this link. */ can find cycles involving this link. */
int err = visit((PyObject *)type, arg); Py_VISIT(type);
if (err)
return err;
}
if (basetraverse) if (basetraverse)
return basetraverse(self, visit, arg); return basetraverse(self, visit, arg);
@ -2198,32 +2192,21 @@ PyDoc_STRVAR(type_doc,
static int static int
type_traverse(PyTypeObject *type, visitproc visit, void *arg) type_traverse(PyTypeObject *type, visitproc visit, void *arg)
{ {
int err;
/* Because of type_is_gc(), the collector only calls this /* Because of type_is_gc(), the collector only calls this
for heaptypes. */ for heaptypes. */
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE); assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
#define VISIT(SLOT) \ Py_VISIT(type->tp_dict);
if (SLOT) { \ Py_VISIT(type->tp_cache);
err = visit((PyObject *)(SLOT), arg); \ Py_VISIT(type->tp_mro);
if (err) \ Py_VISIT(type->tp_bases);
return err; \ Py_VISIT(type->tp_base);
}
VISIT(type->tp_dict);
VISIT(type->tp_cache);
VISIT(type->tp_mro);
VISIT(type->tp_bases);
VISIT(type->tp_base);
/* There's no need to visit type->tp_subclasses or /* There's no need to visit type->tp_subclasses or
((PyHeapTypeObject *)type)->ht_slots, because they can't be involved ((PyHeapTypeObject *)type)->ht_slots, because they can't be involved
in cycles; tp_subclasses is a list of weak references, in cycles; tp_subclasses is a list of weak references,
and slots is a tuple of strings. */ and slots is a tuple of strings. */
#undef VISIT
return 0; return 0;
} }
@ -5805,20 +5788,10 @@ static int
super_traverse(PyObject *self, visitproc visit, void *arg) super_traverse(PyObject *self, visitproc visit, void *arg)
{ {
superobject *su = (superobject *)self; superobject *su = (superobject *)self;
int err;
#define VISIT(SLOT) \ Py_VISIT(su->obj);
if (SLOT) { \ Py_VISIT(su->type);
err = visit((PyObject *)(SLOT), arg); \ Py_VISIT(su->obj_type);
if (err) \
return err; \
}
VISIT(su->obj);
VISIT(su->type);
VISIT(su->obj_type);
#undef VISIT
return 0; return 0;
} }

View file

@ -109,8 +109,7 @@ weakref_dealloc(PyObject *self)
static int static int
gc_traverse(PyWeakReference *self, visitproc visit, void *arg) gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
{ {
if (self->wr_callback != NULL) Py_VISIT(self->wr_callback);
return visit(self->wr_callback, arg);
return 0; return 0;
} }

View file

@ -39,15 +39,9 @@ tb_dealloc(PyTracebackObject *tb)
static int static int
tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg) tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
{ {
int err = 0; Py_VISIT(tb->tb_next);
if (tb->tb_next) { Py_VISIT(tb->tb_frame);
err = visit((PyObject *)tb->tb_next, arg); return 0;
if (err)
return err;
}
if (tb->tb_frame)
err = visit((PyObject *)tb->tb_frame, arg);
return err;
} }
static void static void