summaryrefslogtreecommitdiff
path: root/Cython/Utility/ModuleSetupCode.c
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2017-07-31 22:40:15 +0200
committerStefan Behnel <stefan_ml@behnel.de>2017-07-31 23:18:33 +0200
commitcbec2d11b267a9390feedb80b8379ab1feab5d90 (patch)
tree97070ec3d465812715f83bedad17504eb3f15bdb /Cython/Utility/ModuleSetupCode.c
parentb797b42771b179744d7652794e9c197a720bb4e4 (diff)
downloadcython-cbec2d11b267a9390feedb80b8379ab1feab5d90.tar.gz
speed up type checks, especially for exceptions (which are used a lot in yield/await)
Diffstat (limited to 'Cython/Utility/ModuleSetupCode.c')
-rw-r--r--Cython/Utility/ModuleSetupCode.c106
1 files changed, 105 insertions, 1 deletions
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index d882f4b21..7674b87ea 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -326,7 +326,6 @@
#define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type)
#endif
-#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception)
#if PY_MAJOR_VERSION >= 3
@@ -537,6 +536,111 @@ class __Pyx_FakeReference {
};
+/////////////// FastTypeChecks.proto ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type)
+static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b);/*proto*/
+static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type);/*proto*/
+static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2);/*proto*/
+#else
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type)
+#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2))
+#endif
+
+/////////////// FastTypeChecks ///////////////
+//@requires: Exceptions.c::PyThreadStateGet
+//@requires: Exceptions.c::PyErrFetchRestore
+
+#if CYTHON_COMPILING_IN_CPYTHON
+static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) {
+ while (a) {
+ a = a->tp_base;
+ if (a == b)
+ return 1;
+ }
+ return b == &PyBaseObject_Type;
+}
+
+static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) {
+ PyObject *mro;
+ if (a == b) return 1;
+ mro = a->tp_mro;
+ if (likely(mro)) {
+ Py_ssize_t i, n;
+ n = PyTuple_GET_SIZE(mro);
+ for (i = 0; i < n; i++) {
+ if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)
+ return 1;
+ }
+ return 0;
+ }
+ // should only get here for incompletely initialised types, i.e. never under normal usage patterns
+ return __Pyx_InBases(a, b);
+}
+
+
+#if PY_MAJOR_VERSION == 2
+static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyTypeObject *err, PyTypeObject* exc_type1, PyTypeObject* exc_type2) {
+ // PyObject_IsSubclass() can recurse and therefore is not safe
+ PyObject *exception, *value, *tb;
+ int res;
+ __Pyx_PyThreadState_declare
+ __Pyx_PyThreadState_assign
+ __Pyx_ErrFetch(&exception, &value, &tb);
+
+ res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0;
+ // This function must not fail, so print the error here
+ if (unlikely(res == -1)) {
+ PyErr_WriteUnraisable(err);
+ res = 0;
+ }
+ if (!res) {
+ __Pyx_ErrRestore(exception, value, tb);
+ res = PyObject_IsSubclass(err, exc_type2);
+ // This function must not fail, so print the error here
+ if (unlikely(res == -1)) {
+ PyErr_WriteUnraisable(err);
+ res = 0;
+ }
+ }
+
+ __Pyx_ErrRestore(exception, value, tb);
+ return res;
+}
+#else
+static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyTypeObject *err, PyTypeObject* exc_type1, PyTypeObject* exc_type2) {
+ int res = exc_type1 ? __Pyx_IsSubtype(err, exc_type1) : 0;
+ if (!res) {
+ res = __Pyx_IsSubtype(err, exc_type2);
+ }
+ return res;
+}
+#endif
+
+// so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument
+// => optimise for that case
+
+static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) {
+ if (likely(err == exc_type)) return 1;
+ if (likely(PyExceptionClass_Check(err))) {
+ return __Pyx_inner_PyErr_GivenExceptionMatches2((PyTypeObject *)err, NULL, (PyTypeObject *)exc_type);
+ }
+ return PyErr_GivenExceptionMatches(err, exc_type);
+}
+
+static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) {
+ if (likely(err == exc_type1 || err == exc_type2)) return 1;
+ if (likely(PyExceptionClass_Check(err))) {
+ return __Pyx_inner_PyErr_GivenExceptionMatches2((PyTypeObject *)err, (PyTypeObject *)exc_type1, (PyTypeObject *)exc_type2);
+ }
+ return (PyErr_GivenExceptionMatches(err, exc_type1) || PyErr_GivenExceptionMatches(err, exc_type2));
+}
+
+#endif
+
+
/////////////// MathInitCode ///////////////
#if defined(WIN32) || defined(MS_WINDOWS)