diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-01-18 09:38:09 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2017-01-18 09:38:09 (GMT) |
commit | c52572319cbd50adff85050a54122c25239a516d (patch) | |
tree | 41e964e6b6a25c655496561a32ce97c0f14ce253 /Objects/methodobject.c | |
parent | 35ecebe165b1f64cb94c1b947db1d0b07e6db69b (diff) | |
download | cpython-c52572319cbd50adff85050a54122c25239a516d.zip cpython-c52572319cbd50adff85050a54122c25239a516d.tar.gz cpython-c52572319cbd50adff85050a54122c25239a516d.tar.bz2 |
Optimize methoddescr_call(): avoid temporary PyCFunction
Issue #29259, #29263. methoddescr_call() creates a PyCFunction object, call it
and the destroy it. Add a new _PyMethodDef_RawFastCallDict() method to avoid
the temporary PyCFunction object.
Diffstat (limited to 'Objects/methodobject.c')
-rw-r--r-- | Objects/methodobject.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 1d55a0c..054cf53 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -152,17 +152,14 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds) } PyObject * -_PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, - PyObject *kwargs) +_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **args, + Py_ssize_t nargs, PyObject *kwargs) { - PyCFunctionObject *func; PyCFunction meth; - PyObject *self; PyObject *result; int flags; - assert(func_obj != NULL); - assert(PyCFunction_Check(func_obj)); + assert(method != NULL); assert(nargs >= 0); assert(nargs == 0 || args != NULL); assert(kwargs == NULL || PyDict_Check(kwargs)); @@ -172,10 +169,8 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, caller loses its exception */ assert(!PyErr_Occurred()); - func = (PyCFunctionObject*)func_obj; - meth = PyCFunction_GET_FUNCTION(func); - self = PyCFunction_GET_SELF(func); - flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); + meth = method->ml_meth; + flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); switch (flags) { @@ -186,7 +181,7 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", - func->m_ml->ml_name); + method->ml_name); return NULL; } @@ -197,7 +192,7 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, if (nargs != 1) { PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", - func->m_ml->ml_name, nargs); + method->ml_name, nargs); return NULL; } @@ -259,18 +254,32 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, return NULL; } - result = _Py_CheckFunctionResult(func_obj, result, NULL); - return result; no_keyword_error: PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", - func->m_ml->ml_name, nargs); + method->ml_name, nargs); return NULL; } PyObject * +_PyCFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, + PyObject *kwargs) +{ + PyObject *result; + + assert(func != NULL); + assert(PyCFunction_Check(func)); + + result = _PyMethodDef_RawFastCallDict(((PyCFunctionObject*)func)->m_ml, + PyCFunction_GET_SELF(func), + args, nargs, kwargs); + result = _Py_CheckFunctionResult(func, result, NULL); + return result; +} + +PyObject * _PyCFunction_FastCallKeywords(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { |