Refactored the update_slot() code a bit to be hopefully slightly more

efficient:

- recurse down subclasses only once rather than for each affected
  slot;

- short-circuit recursing down subclasses when a subclass has its own
  definition of the name that caused the update_slot() calls in the
  first place;

- inline collect_ptrs().
This commit is contained in:
Guido van Rossum 2001-10-16 17:00:48 +00:00
parent 26633f4c00
commit b85a8b7bc7
1 changed files with 61 additions and 57 deletions

View File

@ -3764,23 +3764,24 @@ slotptr(PyTypeObject *type, int offset)
return (void **)ptr; return (void **)ptr;
} }
staticforward int recurse_down_subclasses(PyTypeObject *type, slotdef *p); staticforward int recurse_down_subclasses(PyTypeObject *type,
slotdef **pp, PyObject *name);
static int static int
update_one_slot(PyTypeObject *type, slotdef *p0) update_these_slots(PyTypeObject *type, slotdef **pp0, PyObject *name)
{ {
slotdef *p = p0; slotdef **pp;
for (pp = pp0; *pp; pp++) {
slotdef *p = *pp;
PyObject *descr; PyObject *descr;
PyWrapperDescrObject *d; PyWrapperDescrObject *d;
void *generic = NULL, *specific = NULL; void *generic = NULL, *specific = NULL;
int use_generic = 0; int use_generic = 0;
int offset; int offset = p->offset;
void **ptr; void **ptr = slotptr(type, offset);
offset = p->offset;
ptr = slotptr(type, offset);
if (ptr == NULL) if (ptr == NULL)
return recurse_down_subclasses(type, p); continue;
do { do {
descr = _PyType_Lookup(type, p->name_strobj); descr = _PyType_Lookup(type, p->name_strobj);
if (descr == NULL) if (descr == NULL)
@ -3804,14 +3805,15 @@ update_one_slot(PyTypeObject *type, slotdef *p0)
*ptr = specific; *ptr = specific;
else else
*ptr = generic; *ptr = generic;
return recurse_down_subclasses(type, p0); }
return recurse_down_subclasses(type, pp0, name);
} }
static int static int
recurse_down_subclasses(PyTypeObject *type, slotdef *p) recurse_down_subclasses(PyTypeObject *type, slotdef **pp, PyObject *name)
{ {
PyTypeObject *subclass; PyTypeObject *subclass;
PyObject *ref, *subclasses; PyObject *ref, *subclasses, *dict;
int i, n; int i, n;
subclasses = type->tp_subclasses; subclasses = type->tp_subclasses;
@ -3826,7 +3828,12 @@ recurse_down_subclasses(PyTypeObject *type, slotdef *p)
if (subclass == NULL) if (subclass == NULL)
continue; continue;
assert(PyType_Check(subclass)); assert(PyType_Check(subclass));
if (update_one_slot(subclass, p) < 0) /* Avoid recursing down into unaffected classes */
dict = subclass->tp_dict;
if (dict != NULL && PyDict_Check(dict) &&
PyDict_GetItem(dict, name) != NULL)
continue;
if (update_these_slots(subclass, pp, name) < 0)
return -1; return -1;
} }
return 0; return 0;
@ -3856,39 +3863,35 @@ init_slotdefs(void)
if (!p->name_strobj) if (!p->name_strobj)
Py_FatalError("XXX ouch"); Py_FatalError("XXX ouch");
} }
qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef), slotdef_cmp); qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef),
slotdef_cmp);
initialized = 1; initialized = 1;
} }
static void
collect_ptrs(PyObject *name, slotdef *ptrs[])
{
slotdef *p;
init_slotdefs();
for (p = slotdefs; p->name; p++) {
if (name == p->name_strobj)
*ptrs++ = p;
}
*ptrs = NULL;
}
static int static int
update_slot(PyTypeObject *type, PyObject *name) update_slot(PyTypeObject *type, PyObject *name)
{ {
slotdef *ptrs[10]; slotdef *ptrs[10];
slotdef *p; slotdef *p;
slotdef **pp; slotdef **pp;
int offset;
collect_ptrs(name, ptrs); init_slotdefs();
pp = ptrs;
for (p = slotdefs; p->name; p++) {
/* XXX assume name is interned! */
if (p->name_strobj == name)
*pp++ = p;
}
*pp = NULL;
for (pp = ptrs; *pp; pp++) { for (pp = ptrs; *pp; pp++) {
p = *pp; p = *pp;
while (p > slotdefs && p->offset == (p-1)->offset) offset = p->offset;
while (p > slotdefs && (p-1)->offset == offset)
--p; --p;
if (update_one_slot(type, p) < 0) *pp = p;
return -1;
} }
return 0; return update_these_slots(type, ptrs, name);
} }
static void static void
@ -3921,7 +3924,8 @@ fixup_slot_dispatchers(PyTypeObject *type)
do { do {
descr = NULL; descr = NULL;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
base = (PyTypeObject *)PyTuple_GET_ITEM(mro, i); base = (PyTypeObject *)
PyTuple_GET_ITEM(mro, i);
assert(PyType_Check(base)); assert(PyType_Check(base));
descr = PyDict_GetItem( descr = PyDict_GetItem(
base->tp_dict, p->name_strobj); base->tp_dict, p->name_strobj);