Commit ba9a6366 authored by Stefan Behnel's avatar Stefan Behnel Committed by GitHub

Merge pull request #2769 from cython/faster_getattr

Speed up attribute lookups that do not care about the AttributeError
parents 4e35b1a3 de109c20
...@@ -167,7 +167,7 @@ bad: ...@@ -167,7 +167,7 @@ bad:
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/ static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
//////////////////// GetAttr3 //////////////////// //////////////////// GetAttr3 ////////////////////
//@requires: ObjectHandling.c::GetAttr //@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: Exceptions.c::PyThreadStateGet //@requires: Exceptions.c::PyThreadStateGet
//@requires: Exceptions.c::PyErrFetchRestore //@requires: Exceptions.c::PyErrFetchRestore
//@requires: Exceptions.c::PyErrExceptionMatches //@requires: Exceptions.c::PyErrExceptionMatches
...@@ -183,7 +183,17 @@ static PyObject *__Pyx_GetAttr3Default(PyObject *d) { ...@@ -183,7 +183,17 @@ static PyObject *__Pyx_GetAttr3Default(PyObject *d) {
} }
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) { static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
PyObject *r = __Pyx_GetAttr(o, n); PyObject *r;
#if CYTHON_USE_TYPE_SLOTS
if (likely(PyString_Check(n))) {
r = __Pyx_PyObject_GetAttrStrNoError(o, n);
if (unlikely(!r) && likely(!PyErr_Occurred())) {
r = __Pyx_NewRef(d);
}
return r;
}
#endif
r = PyObject_GetAttr(o, n);
return (likely(r)) ? r : __Pyx_GetAttr3Default(d); return (likely(r)) ? r : __Pyx_GetAttr3Default(d);
} }
......
...@@ -485,6 +485,7 @@ static int __pyx_Generator_init(void); /*proto*/ ...@@ -485,6 +485,7 @@ static int __pyx_Generator_init(void); /*proto*/
//@requires: Exceptions.c::SaveResetException //@requires: Exceptions.c::SaveResetException
//@requires: ObjectHandling.c::PyObjectCallMethod1 //@requires: ObjectHandling.c::PyObjectCallMethod1
//@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: CommonStructures.c::FetchCommonType //@requires: CommonStructures.c::FetchCommonType
#include <structmember.h> #include <structmember.h>
...@@ -894,12 +895,11 @@ static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) { ...@@ -894,12 +895,11 @@ static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) {
{ {
PyObject *meth; PyObject *meth;
gen->is_running = 1; gen->is_running = 1;
meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("close")); meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("close"));
if (unlikely(!meth)) { if (unlikely(!meth)) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { if (unlikely(PyErr_Occurred())) {
PyErr_WriteUnraisable(yf); PyErr_WriteUnraisable(yf);
} }
PyErr_Clear();
} else { } else {
retval = PyObject_CallFunction(meth, NULL); retval = PyObject_CallFunction(meth, NULL);
Py_DECREF(meth); Py_DECREF(meth);
...@@ -1041,14 +1041,13 @@ static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject ...@@ -1041,14 +1041,13 @@ static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject
ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit); ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit);
#endif #endif
} else { } else {
PyObject *meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("throw")); PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("throw"));
if (unlikely(!meth)) { if (unlikely(!meth)) {
Py_DECREF(yf); Py_DECREF(yf);
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { if (unlikely(PyErr_Occurred())) {
gen->is_running = 0; gen->is_running = 0;
return NULL; return NULL;
} }
PyErr_Clear();
__Pyx_Coroutine_Undelegate(gen); __Pyx_Coroutine_Undelegate(gen);
gen->is_running = 0; gen->is_running = 0;
goto throw_here; goto throw_here;
......
...@@ -641,7 +641,7 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/ ...@@ -641,7 +641,7 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/
#endif #endif
/////////////// CLineInTraceback /////////////// /////////////// CLineInTraceback ///////////////
//@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: PyErrFetchRestore //@requires: PyErrFetchRestore
//@substitute: naming //@substitute: naming
...@@ -669,7 +669,7 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { ...@@ -669,7 +669,7 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) {
} else } else
#endif #endif
{ {
PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(${cython_runtime_cname}, PYIDENT("cline_in_traceback")); PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStrNoError(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
if (use_cline_obj) { if (use_cline_obj) {
use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True;
Py_DECREF(use_cline_obj); Py_DECREF(use_cline_obj);
......
...@@ -132,6 +132,7 @@ static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) { ...@@ -132,6 +132,7 @@ static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) {
static int __Pyx_setup_reduce(PyObject* type_obj); static int __Pyx_setup_reduce(PyObject* type_obj);
/////////////// SetupReduce /////////////// /////////////// SetupReduce ///////////////
//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: ObjectHandling.c::PyObjectGetAttrStr //@requires: ObjectHandling.c::PyObjectGetAttrStr
//@substitute: naming //@substitute: naming
...@@ -139,7 +140,7 @@ static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) { ...@@ -139,7 +140,7 @@ static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) {
int ret; int ret;
PyObject *name_attr; PyObject *name_attr;
name_attr = __Pyx_PyObject_GetAttrStr(meth, PYIDENT("__name__")); name_attr = __Pyx_PyObject_GetAttrStrNoError(meth, PYIDENT("__name__"));
if (likely(name_attr)) { if (likely(name_attr)) {
ret = PyObject_RichCompareBool(name_attr, name, Py_EQ); ret = PyObject_RichCompareBool(name_attr, name, Py_EQ);
} else { } else {
...@@ -192,7 +193,7 @@ static int __Pyx_setup_reduce(PyObject* type_obj) { ...@@ -192,7 +193,7 @@ static int __Pyx_setup_reduce(PyObject* type_obj) {
ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce__"), reduce_cython); if (unlikely(ret < 0)) goto BAD; ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce__"), reduce_cython); if (unlikely(ret < 0)) goto BAD;
ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce_cython__")); if (unlikely(ret < 0)) goto BAD; ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce_cython__")); if (unlikely(ret < 0)) goto BAD;
setstate = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__setstate__")); setstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate__"));
if (!setstate) PyErr_Clear(); if (!setstate) PyErr_Clear();
if (!setstate || __Pyx_setup_reduce_is_named(setstate, PYIDENT("__setstate_cython__"))) { if (!setstate || __Pyx_setup_reduce_is_named(setstate, PYIDENT("__setstate_cython__"))) {
setstate_cython = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__setstate_cython__")); if (unlikely(!setstate_cython)) goto BAD; setstate_cython = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__setstate_cython__")); if (unlikely(!setstate_cython)) goto BAD;
......
...@@ -943,14 +943,14 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj ...@@ -943,14 +943,14 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); /*proto*/ PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); /*proto*/
/////////////// Py3ClassCreate /////////////// /////////////// Py3ClassCreate ///////////////
//@requires: PyObjectGetAttrStr //@requires: PyObjectGetAttrStrNoError
//@requires: CalculateMetaclass //@requires: CalculateMetaclass
static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name,
PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) { PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) {
PyObject *ns; PyObject *ns;
if (metaclass) { if (metaclass) {
PyObject *prep = __Pyx_PyObject_GetAttrStr(metaclass, PYIDENT("__prepare__")); PyObject *prep = __Pyx_PyObject_GetAttrStrNoError(metaclass, PYIDENT("__prepare__"));
if (prep) { if (prep) {
PyObject *pargs = PyTuple_Pack(2, name, bases); PyObject *pargs = PyTuple_Pack(2, name, bases);
if (unlikely(!pargs)) { if (unlikely(!pargs)) {
...@@ -961,9 +961,8 @@ static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, ...@@ -961,9 +961,8 @@ static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases,
Py_DECREF(prep); Py_DECREF(prep);
Py_DECREF(pargs); Py_DECREF(pargs);
} else { } else {
if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError))) if (unlikely(PyErr_Occurred()))
return NULL; return NULL;
PyErr_Clear();
ns = PyDict_New(); ns = PyDict_New();
} }
} else { } else {
...@@ -1099,12 +1098,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) { ...@@ -1099,12 +1098,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/ static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/
/////////////// GetBuiltinName /////////////// /////////////// GetBuiltinName ///////////////
//@requires: PyObjectGetAttrStr //@requires: PyObjectGetAttrStrNoError
//@substitute: naming //@substitute: naming
static PyObject *__Pyx_GetBuiltinName(PyObject *name) { static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
PyObject* result = __Pyx_PyObject_GetAttrStr($builtins_cname, name); PyObject* result = __Pyx_PyObject_GetAttrStrNoError($builtins_cname, name);
if (unlikely(!result)) { if (unlikely(!result) && !PyErr_Occurred()) {
PyErr_Format(PyExc_NameError, PyErr_Format(PyExc_NameError,
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
"name '%U' is not defined", name); "name '%U' is not defined", name);
...@@ -1121,28 +1120,17 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) { ...@@ -1121,28 +1120,17 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/ static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/
/////////////// GetNameInClass /////////////// /////////////// GetNameInClass ///////////////
//@requires: PyObjectGetAttrStr //@requires: PyObjectGetAttrStrNoError
//@requires: GetModuleGlobalName //@requires: GetModuleGlobalName
//@requires: Exceptions.c::PyThreadStateGet
//@requires: Exceptions.c::PyErrFetchRestore
//@requires: Exceptions.c::PyErrExceptionMatches
static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) { static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
PyObject *result; PyObject *result;
__Pyx_PyThreadState_declare result = __Pyx_PyObject_GetAttrStrNoError(nmspace, name);
__Pyx_PyThreadState_assign if (!result) {
if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError))) if (unlikely(PyErr_Occurred()))
return NULL; return NULL;
__Pyx_PyErr_Clear();
__Pyx_GetModuleGlobalNameUncached(result, name); __Pyx_GetModuleGlobalNameUncached(result, name);
return result; return result;
}
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
PyObject *result;
result = __Pyx_PyObject_GetAttrStr(nmspace, name);
if (!result) {
result = __Pyx_GetGlobalNameAfterAttributeLookup(name);
} }
return result; return result;
} }
...@@ -1358,6 +1346,41 @@ static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_nam ...@@ -1358,6 +1346,41 @@ static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_nam
#endif #endif
/////////////// PyObjectGetAttrStrNoError.proto ///////////////
static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name);/*proto*/
/////////////// PyObjectGetAttrStrNoError ///////////////
//@requires: PyObjectGetAttrStr
//@requires: Exceptions.c::PyThreadStateGet
//@requires: Exceptions.c::PyErrFetchRestore
//@requires: Exceptions.c::PyErrExceptionMatches
static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) {
__Pyx_PyThreadState_declare
__Pyx_PyThreadState_assign
if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
__Pyx_PyErr_Clear();
}
static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) {
PyObject *result;
#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1
// _PyObject_GenericGetAttrWithDict() in CPython 3.7+ can avoid raising the AttributeError.
// See https://bugs.python.org/issue32544
PyTypeObject* tp = Py_TYPE(obj);
if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) {
return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1);
}
#endif
result = __Pyx_PyObject_GetAttrStr(obj, attr_name);
if (unlikely(!result)) {
__Pyx_PyObject_GetAttrStr_ClearAttributeError();
}
return result;
}
/////////////// PyObjectGetAttrStr.proto /////////////// /////////////// PyObjectGetAttrStr.proto ///////////////
#if CYTHON_USE_TYPE_SLOTS #if CYTHON_USE_TYPE_SLOTS
...@@ -2303,7 +2326,7 @@ static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y); ...@@ -2303,7 +2326,7 @@ static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y);
#endif #endif
/////////////// MatrixMultiply /////////////// /////////////// MatrixMultiply ///////////////
//@requires: PyObjectGetAttrStr //@requires: PyObjectGetAttrStrNoError
//@requires: PyObjectCallOneArg //@requires: PyObjectCallOneArg
//@requires: PyFunctionFastCall //@requires: PyFunctionFastCall
//@requires: PyCFunctionFastCall //@requires: PyCFunctionFastCall
...@@ -2354,16 +2377,14 @@ done: ...@@ -2354,16 +2377,14 @@ done:
} }
#define __Pyx_TryMatrixMethod(x, y, py_method_name) { \ #define __Pyx_TryMatrixMethod(x, y, py_method_name) { \
PyObject *func = __Pyx_PyObject_GetAttrStr(x, py_method_name); \ PyObject *func = __Pyx_PyObject_GetAttrStrNoError(x, py_method_name); \
if (func) { \ if (func) { \
PyObject *result = __Pyx_PyObject_CallMatrixMethod(func, y); \ PyObject *result = __Pyx_PyObject_CallMatrixMethod(func, y); \
if (result != Py_NotImplemented) \ if (result != Py_NotImplemented) \
return result; \ return result; \
Py_DECREF(result); \ Py_DECREF(result); \
} else { \ } else if (unlikely(PyErr_Occurred())) { \
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) \
return NULL; \ return NULL; \
PyErr_Clear(); \
} \ } \
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment