mirror of https://github.com/python/cpython
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:
parent
26633f4c00
commit
b85a8b7bc7
|
@ -3764,54 +3764,56 @@ slotptr(PyTypeObject *type, int offset)
|
|||
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
|
||||
update_one_slot(PyTypeObject *type, slotdef *p0)
|
||||
update_these_slots(PyTypeObject *type, slotdef **pp0, PyObject *name)
|
||||
{
|
||||
slotdef *p = p0;
|
||||
PyObject *descr;
|
||||
PyWrapperDescrObject *d;
|
||||
void *generic = NULL, *specific = NULL;
|
||||
int use_generic = 0;
|
||||
int offset;
|
||||
void **ptr;
|
||||
slotdef **pp;
|
||||
|
||||
offset = p->offset;
|
||||
ptr = slotptr(type, offset);
|
||||
if (ptr == NULL)
|
||||
return recurse_down_subclasses(type, p);
|
||||
do {
|
||||
descr = _PyType_Lookup(type, p->name_strobj);
|
||||
if (descr == NULL)
|
||||
for (pp = pp0; *pp; pp++) {
|
||||
slotdef *p = *pp;
|
||||
PyObject *descr;
|
||||
PyWrapperDescrObject *d;
|
||||
void *generic = NULL, *specific = NULL;
|
||||
int use_generic = 0;
|
||||
int offset = p->offset;
|
||||
void **ptr = slotptr(type, offset);
|
||||
if (ptr == NULL)
|
||||
continue;
|
||||
generic = p->function;
|
||||
if (descr->ob_type == &PyWrapperDescr_Type) {
|
||||
d = (PyWrapperDescrObject *)descr;
|
||||
if (d->d_base->wrapper == p->wrapper &&
|
||||
PyType_IsSubtype(type, d->d_type)) {
|
||||
if (specific == NULL ||
|
||||
specific == d->d_wrapped)
|
||||
specific = d->d_wrapped;
|
||||
else
|
||||
use_generic = 1;
|
||||
do {
|
||||
descr = _PyType_Lookup(type, p->name_strobj);
|
||||
if (descr == NULL)
|
||||
continue;
|
||||
generic = p->function;
|
||||
if (descr->ob_type == &PyWrapperDescr_Type) {
|
||||
d = (PyWrapperDescrObject *)descr;
|
||||
if (d->d_base->wrapper == p->wrapper &&
|
||||
PyType_IsSubtype(type, d->d_type)) {
|
||||
if (specific == NULL ||
|
||||
specific == d->d_wrapped)
|
||||
specific = d->d_wrapped;
|
||||
else
|
||||
use_generic = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
use_generic = 1;
|
||||
} while ((++p)->offset == offset);
|
||||
if (specific && !use_generic)
|
||||
*ptr = specific;
|
||||
else
|
||||
use_generic = 1;
|
||||
} while ((++p)->offset == offset);
|
||||
if (specific && !use_generic)
|
||||
*ptr = specific;
|
||||
else
|
||||
*ptr = generic;
|
||||
return recurse_down_subclasses(type, p0);
|
||||
*ptr = generic;
|
||||
}
|
||||
return recurse_down_subclasses(type, pp0, name);
|
||||
}
|
||||
|
||||
static int
|
||||
recurse_down_subclasses(PyTypeObject *type, slotdef *p)
|
||||
recurse_down_subclasses(PyTypeObject *type, slotdef **pp, PyObject *name)
|
||||
{
|
||||
PyTypeObject *subclass;
|
||||
PyObject *ref, *subclasses;
|
||||
PyObject *ref, *subclasses, *dict;
|
||||
int i, n;
|
||||
|
||||
subclasses = type->tp_subclasses;
|
||||
|
@ -3826,7 +3828,12 @@ recurse_down_subclasses(PyTypeObject *type, slotdef *p)
|
|||
if (subclass == NULL)
|
||||
continue;
|
||||
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 0;
|
||||
|
@ -3856,39 +3863,35 @@ init_slotdefs(void)
|
|||
if (!p->name_strobj)
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
update_slot(PyTypeObject *type, PyObject *name)
|
||||
{
|
||||
slotdef *ptrs[10];
|
||||
slotdef *p;
|
||||
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++) {
|
||||
p = *pp;
|
||||
while (p > slotdefs && p->offset == (p-1)->offset)
|
||||
offset = p->offset;
|
||||
while (p > slotdefs && (p-1)->offset == offset)
|
||||
--p;
|
||||
if (update_one_slot(type, p) < 0)
|
||||
return -1;
|
||||
*pp = p;
|
||||
}
|
||||
return 0;
|
||||
return update_these_slots(type, ptrs, name);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3921,7 +3924,8 @@ fixup_slot_dispatchers(PyTypeObject *type)
|
|||
do {
|
||||
descr = NULL;
|
||||
for (i = 0; i < n; i++) {
|
||||
base = (PyTypeObject *)PyTuple_GET_ITEM(mro, i);
|
||||
base = (PyTypeObject *)
|
||||
PyTuple_GET_ITEM(mro, i);
|
||||
assert(PyType_Check(base));
|
||||
descr = PyDict_GetItem(
|
||||
base->tp_dict, p->name_strobj);
|
||||
|
|
Loading…
Reference in New Issue