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;
|
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;
|
||||||
PyObject *descr;
|
|
||||||
PyWrapperDescrObject *d;
|
|
||||||
void *generic = NULL, *specific = NULL;
|
|
||||||
int use_generic = 0;
|
|
||||||
int offset;
|
|
||||||
void **ptr;
|
|
||||||
|
|
||||||
offset = p->offset;
|
for (pp = pp0; *pp; pp++) {
|
||||||
ptr = slotptr(type, offset);
|
slotdef *p = *pp;
|
||||||
if (ptr == NULL)
|
PyObject *descr;
|
||||||
return recurse_down_subclasses(type, p);
|
PyWrapperDescrObject *d;
|
||||||
do {
|
void *generic = NULL, *specific = NULL;
|
||||||
descr = _PyType_Lookup(type, p->name_strobj);
|
int use_generic = 0;
|
||||||
if (descr == NULL)
|
int offset = p->offset;
|
||||||
|
void **ptr = slotptr(type, offset);
|
||||||
|
if (ptr == NULL)
|
||||||
continue;
|
continue;
|
||||||
generic = p->function;
|
do {
|
||||||
if (descr->ob_type == &PyWrapperDescr_Type) {
|
descr = _PyType_Lookup(type, p->name_strobj);
|
||||||
d = (PyWrapperDescrObject *)descr;
|
if (descr == NULL)
|
||||||
if (d->d_base->wrapper == p->wrapper &&
|
continue;
|
||||||
PyType_IsSubtype(type, d->d_type)) {
|
generic = p->function;
|
||||||
if (specific == NULL ||
|
if (descr->ob_type == &PyWrapperDescr_Type) {
|
||||||
specific == d->d_wrapped)
|
d = (PyWrapperDescrObject *)descr;
|
||||||
specific = d->d_wrapped;
|
if (d->d_base->wrapper == p->wrapper &&
|
||||||
else
|
PyType_IsSubtype(type, d->d_type)) {
|
||||||
use_generic = 1;
|
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
|
else
|
||||||
use_generic = 1;
|
*ptr = generic;
|
||||||
} while ((++p)->offset == offset);
|
}
|
||||||
if (specific && !use_generic)
|
return recurse_down_subclasses(type, pp0, name);
|
||||||
*ptr = specific;
|
|
||||||
else
|
|
||||||
*ptr = generic;
|
|
||||||
return recurse_down_subclasses(type, p0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue