]> granicus.if.org Git - python/commitdiff
Refactored the update_slot() code a bit to be hopefully slightly more
authorGuido van Rossum <guido@python.org>
Tue, 16 Oct 2001 17:00:48 +0000 (17:00 +0000)
committerGuido van Rossum <guido@python.org>
Tue, 16 Oct 2001 17:00:48 +0000 (17:00 +0000)
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().

Objects/typeobject.c

index 901d0268049f8773e169ae7a7bdaa428ab8edc9a..363c562fd915e77b90bc0dffa139ee5f5954c1b9 100644 (file)
@@ -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);