Commit 6ca9672c authored by Stefan Behnel's avatar Stefan Behnel

Fold bound method unpacking into method lookup to 1) reduce code duplication...

Fold bound method unpacking into method lookup to 1) reduce code duplication and 2) at least avoid keeping the method object around any longer than necessary if we couldn't avoid creating it in the first place.
parent 3e8d6a04
...@@ -103,7 +103,7 @@ static int __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o) { ...@@ -103,7 +103,7 @@ static int __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o) {
//@requires: AsyncGeneratorInitFinalizer //@requires: AsyncGeneratorInitFinalizer
//@requires: Coroutine.c::Coroutine //@requires: Coroutine.c::Coroutine
//@requires: Coroutine.c::ReturnWithStopIteration //@requires: Coroutine.c::ReturnWithStopIteration
//@requires: ObjectHandling.c::PyObjectCallMethod1 //@requires: ObjectHandling.c::PyObjectCall2Args
//@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict //@requires: ObjectHandling.c::PyObject_GenericGetAttrNoDict
PyDoc_STRVAR(__Pyx_async_gen_send_doc, PyDoc_STRVAR(__Pyx_async_gen_send_doc,
...@@ -226,7 +226,16 @@ __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o) ...@@ -226,7 +226,16 @@ __Pyx_async_gen_init_hooks(__pyx_PyAsyncGenObject *o)
Py_INCREF(firstiter); Py_INCREF(firstiter);
// at least asyncio stores methods here => optimise the call // at least asyncio stores methods here => optimise the call
res = __Pyx__PyObject_CallMethod1(firstiter, (PyObject*)o); #if CYTHON_UNPACK_METHODS
if (likely(PyMethod_Check(firstiter))) {
PyObject *self = PyMethod_GET_SELF(firstiter);
if (likely(self)) {
PyObject *function = PyMethod_GET_FUNCTION(firstiter);
return __Pyx_PyObject_Call2Args(function, self, (PyObject*)o);
}
}
#endif
res = __Pyx_PyObject_CallOneArg(firstiter, (PyObject*)o);
Py_DECREF(firstiter); Py_DECREF(firstiter);
if (unlikely(res == NULL)) { if (unlikely(res == NULL)) {
return 1; return 1;
......
...@@ -1413,20 +1413,20 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me ...@@ -1413,20 +1413,20 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
#if CYTHON_UNPACK_METHODS #if CYTHON_UNPACK_METHODS
static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) {
PyObject *attr;
#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP #if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP
// Copied from _PyObject_GetMethod() in CPython 3.7 // Copied from _PyObject_GetMethod() in CPython 3.7
PyTypeObject *tp = Py_TYPE(obj); PyTypeObject *tp = Py_TYPE(obj);
PyObject *descr; PyObject *descr;
descrgetfunc f = NULL; descrgetfunc f = NULL;
PyObject **dictptr, *dict; PyObject **dictptr, *dict;
PyObject *attr;
int meth_found = 0; int meth_found = 0;
assert (*method == NULL); assert (*method == NULL);
if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) {
*method = __Pyx_PyObject_GetAttrStr(obj, name); attr = __Pyx_PyObject_GetAttrStr(obj, name);
return 0; goto try_unpack;
} }
if (unlikely(tp->tp_dict == NULL && PyType_Ready(tp) < 0)) { if (unlikely(tp->tp_dict == NULL && PyType_Ready(tp) < 0)) {
return 0; return 0;
...@@ -1445,9 +1445,9 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me ...@@ -1445,9 +1445,9 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
} else { } else {
f = Py_TYPE(descr)->tp_descr_get; f = Py_TYPE(descr)->tp_descr_get;
if (f != NULL && PyDescr_IsData(descr)) { if (f != NULL && PyDescr_IsData(descr)) {
*method = f(descr, obj, (PyObject *)Py_TYPE(obj)); attr = f(descr, obj, (PyObject *)Py_TYPE(obj));
Py_DECREF(descr); Py_DECREF(descr);
return 0; goto try_unpack;
} }
} }
} }
...@@ -1458,10 +1458,9 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me ...@@ -1458,10 +1458,9 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
attr = __Pyx_PyDict_GetItemStr(dict, name); attr = __Pyx_PyDict_GetItemStr(dict, name);
if (attr != NULL) { if (attr != NULL) {
Py_INCREF(attr); Py_INCREF(attr);
*method = attr;
Py_DECREF(dict); Py_DECREF(dict);
Py_XDECREF(descr); Py_XDECREF(descr);
return 0; goto try_unpack;
} }
Py_DECREF(dict); Py_DECREF(dict);
} }
...@@ -1472,9 +1471,9 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me ...@@ -1472,9 +1471,9 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
} }
if (f != NULL) { if (f != NULL) {
*method = f(descr, obj, (PyObject *)Py_TYPE(obj)); attr = f(descr, obj, (PyObject *)Py_TYPE(obj));
Py_DECREF(descr); Py_DECREF(descr);
return 0; goto try_unpack;
} }
if (descr != NULL) { if (descr != NULL) {
...@@ -1494,9 +1493,23 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me ...@@ -1494,9 +1493,23 @@ static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **me
// Generic fallback implementation using normal attribute lookup. // Generic fallback implementation using normal attribute lookup.
#else #else
*method = __Pyx_PyObject_GetAttrStr(obj, name); attr = __Pyx_PyObject_GetAttrStr(obj, name);
return 0; goto try_unpack;
#endif #endif
try_unpack:
#if CYTHON_COMPILING_IN_CPYTHON
// Even if we failed to avoid creating a bound method object, it's still worth unpacking it now, if possible.
if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) {
PyObject *function = PyMethod_GET_FUNCTION(attr);
Py_INCREF(function);
Py_DECREF(attr);
*method = function;
return 1;
}
#endif
*method = attr;
return 0;
} }
#endif #endif
...@@ -1755,7 +1768,6 @@ bad: ...@@ -1755,7 +1768,6 @@ bad:
/////////////// PyObjectCallMethod1.proto /////////////// /////////////// PyObjectCallMethod1.proto ///////////////
static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); /*proto*/ static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name, PyObject* arg); /*proto*/
static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg); /*proto*/
/////////////// PyObjectCallMethod1 /////////////// /////////////// PyObjectCallMethod1 ///////////////
//@requires: PyObjectGetMethod //@requires: PyObjectGetMethod
...@@ -1764,17 +1776,9 @@ static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg); / ...@@ -1764,17 +1776,9 @@ static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg); /
//@requires: PyObjectCall2Args //@requires: PyObjectCall2Args
static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) { static PyObject* __Pyx__PyObject_CallMethod1(PyObject* method, PyObject* arg) {
PyObject *result = NULL; // Separate function to avoid excessive inlining.
#if CYTHON_UNPACK_METHODS PyObject *result = __Pyx_PyObject_CallOneArg(method, arg);
if (likely(PyMethod_Check(method))) { Py_DECREF(method);
PyObject *self = PyMethod_GET_SELF(method);
if (likely(self)) {
PyObject *function = PyMethod_GET_FUNCTION(method);
return __Pyx_PyObject_Call2Args(function, self, arg);
}
}
#endif
result = __Pyx_PyObject_CallOneArg(method, arg);
return result; return result;
} }
...@@ -1791,9 +1795,7 @@ static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name ...@@ -1791,9 +1795,7 @@ static PyObject* __Pyx_PyObject_CallMethod1(PyObject* obj, PyObject* method_name
method = __Pyx_PyObject_GetAttrStr(obj, method_name); method = __Pyx_PyObject_GetAttrStr(obj, method_name);
#endif #endif
if (unlikely(!method)) return NULL; if (unlikely(!method)) return NULL;
result = __Pyx__PyObject_CallMethod1(method, arg); return __Pyx__PyObject_CallMethod1(method, arg);
Py_DECREF(method);
return result;
} }
...@@ -1838,18 +1840,6 @@ static PyObject* __Pyx_PyObject_Call3Args(PyObject* function, PyObject* arg1, Py ...@@ -1838,18 +1840,6 @@ static PyObject* __Pyx_PyObject_Call3Args(PyObject* function, PyObject* arg1, Py
} }
#endif #endif
static PyObject* __Pyx__PyObject_CallMethod2(PyObject* obj, PyObject* method_name, PyObject* arg1, PyObject* arg2) {
#if CYTHON_UNPACK_METHODS
if (likely(PyMethod_Check(method)) && likely(PyMethod_GET_SELF(method))) {
PyObject *self, *function;
self = PyMethod_GET_SELF(method);
function = PyMethod_GET_FUNCTION(method);
return __Pyx_PyObject_Call3Args(method, obj, arg1, arg2);
}
#endif
return __Pyx_PyObject_Call2Args(method, arg1, arg2);
}
static PyObject* __Pyx_PyObject_CallMethod2(PyObject* obj, PyObject* method_name, PyObject* arg1, PyObject* arg2) { static PyObject* __Pyx_PyObject_CallMethod2(PyObject* obj, PyObject* method_name, PyObject* arg1, PyObject* arg2) {
PyObject *args, *method = NULL, *result = NULL; PyObject *args, *method = NULL, *result = NULL;
#if CYTHON_UNPACK_METHODS #if CYTHON_UNPACK_METHODS
...@@ -1863,7 +1853,7 @@ static PyObject* __Pyx_PyObject_CallMethod2(PyObject* obj, PyObject* method_name ...@@ -1863,7 +1853,7 @@ static PyObject* __Pyx_PyObject_CallMethod2(PyObject* obj, PyObject* method_name
method = __Pyx_PyObject_GetAttrStr(obj, method_name); method = __Pyx_PyObject_GetAttrStr(obj, method_name);
#endif #endif
if (unlikely(!method)) return NULL; if (unlikely(!method)) return NULL;
result = __Pyx__PyObject_CallMethod2(method, arg1, arg2); result = __Pyx_PyObject_Call2Args(method, arg1, arg2);
Py_DECREF(method); Py_DECREF(method);
return result; return result;
} }
......
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