]> granicus.if.org Git - python/commitdiff
Closes #22540: speed up PyObject_IsInstance and PyObject_IsSubclass in the common...
authorGeorg Brandl <georg@python.org>
Fri, 3 Oct 2014 07:26:37 +0000 (09:26 +0200)
committerGeorg Brandl <georg@python.org>
Fri, 3 Oct 2014 07:26:37 +0000 (09:26 +0200)
Misc/NEWS
Objects/abstract.c

index 7d8a8000fa298ef147b5efa1034bf900ecfdfb48..dda3843fc893fdfc6b4a1e95f42341fb4c1e2477 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: TBA
 Core and Builtins
 -----------------
 
+- Issue #22540: speed up `PyObject_IsInstance` and `PyObject_IsSubclass` in the
+  common case that the second argument has metaclass `type`.
+
 - Issue #18711: Add a new `PyErr_FormatV` function, similar to `PyErr_Format`
   but accepting a `va_list` argument.
 
index ec599723ac659fef8718eb4166c90cc3f706cf27..177c34a4a4e8f56106aa8a9b6f362d6d5c1a1a58 100644 (file)
@@ -2538,6 +2538,11 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
     if (Py_TYPE(inst) == (PyTypeObject *)cls)
         return 1;
 
+    /* We know what type's __instancecheck__ does. */
+    if (PyType_CheckExact(cls)) {
+        return recursive_isinstance(inst, cls);
+    }
+
     if (PyTuple_Check(cls)) {
         Py_ssize_t i;
         Py_ssize_t n;
@@ -2576,6 +2581,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
     }
     else if (PyErr_Occurred())
         return -1;
+    /* Probably never reached anymore. */
     return recursive_isinstance(inst, cls);
 }
 
@@ -2603,6 +2609,14 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
     _Py_IDENTIFIER(__subclasscheck__);
     PyObject *checker;
 
+    /* We know what type's __subclasscheck__ does. */
+    if (PyType_CheckExact(cls)) {
+        /* Quick test for an exact match */
+        if (derived == cls)
+            return 1;
+        return recursive_issubclass(derived, cls);
+    }
+
     if (PyTuple_Check(cls)) {
         Py_ssize_t i;
         Py_ssize_t n;
@@ -2641,6 +2655,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
     }
     else if (PyErr_Occurred())
         return -1;
+    /* Probably never reached anymore. */
     return recursive_issubclass(derived, cls);
 }