summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-10-16 17:00:48 (GMT)
committerGuido van Rossum <guido@python.org>2001-10-16 17:00:48 (GMT)
commitb85a8b7bc79179c97ad1e7f876f885166f855cc8 (patch)
tree079f870efcd0a69c40daee658154a978d8b7fbb0 /Objects
parent26633f4c00d64eca243c3893b8ec106cfba46a71 (diff)
downloadcpython-b85a8b7bc79179c97ad1e7f876f885166f855cc8.zip
cpython-b85a8b7bc79179c97ad1e7f876f885166f855cc8.tar.gz
cpython-b85a8b7bc79179c97ad1e7f876f885166f855cc8.tar.bz2
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().
Diffstat (limited to 'Objects')
-rw-r--r--Objects/typeobject.c118
1 files changed, 61 insertions, 57 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 901d026..363c562 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -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);