diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-08-22 10:29:42 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-08-22 10:29:42 (GMT) |
commit | 2eedc119c211a793d0c9a0beb1abd4bb12e0802e (patch) | |
tree | 694f45281e7eeeab91a58024632e3c3f711d5c4d /Python | |
parent | 0add84b9b855c10e9c6434286c2b1157a754a39f (diff) | |
download | cpython-2eedc119c211a793d0c9a0beb1abd4bb12e0802e.zip cpython-2eedc119c211a793d0c9a0beb1abd4bb12e0802e.tar.gz cpython-2eedc119c211a793d0c9a0beb1abd4bb12e0802e.tar.bz2 |
Optimize call to Python function without argument
Issue #27128. When a Python function is called with no arguments, but all
parameters have a default value: use default values as arguments for the fast
path.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index d16e932..bd0cbe7 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4801,8 +4801,8 @@ call_function(PyObject ***pp_stack, int oparg */ static PyObject* -_PyFunction_FastCallNoKw(PyObject **args, Py_ssize_t na, - PyCodeObject *co, PyObject *globals) +_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { PyFrameObject *f; PyThreadState *tstate = PyThreadState_GET(); @@ -4837,8 +4837,10 @@ _PyFunction_FastCallNoKw(PyObject **args, Py_ssize_t na, return result; } +/* Similar to _PyFunction_FastCall() but keywords are passed a (key, value) + pairs in stack */ static PyObject * -fast_function(PyObject *func, PyObject **stack, int n, int na, int nk) +fast_function(PyObject *func, PyObject **stack, int n, int nargs, int nk) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); @@ -4850,11 +4852,20 @@ fast_function(PyObject *func, PyObject **stack, int n, int na, int nk) PCALL(PCALL_FUNCTION); PCALL(PCALL_FAST_FUNCTION); - if (argdefs == NULL && co->co_argcount == na && - co->co_kwonlyargcount == 0 && nk == 0 && + if (co->co_kwonlyargcount == 0 && nk == 0 && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - return _PyFunction_FastCallNoKw(stack, na, co, globals); + if (argdefs == NULL && co->co_argcount == nargs) { + return _PyFunction_FastCallNoKw(co, stack, nargs, globals); + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + stack = &PyTuple_GET_ITEM(argdefs, 0); + return _PyFunction_FastCallNoKw(co, stack, Py_SIZE(argdefs), + globals); + } } kwdefs = PyFunction_GET_KW_DEFAULTS(func); @@ -4871,8 +4882,8 @@ fast_function(PyObject *func, PyObject **stack, int n, int na, int nk) nd = 0; } return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, - stack, na, - stack + na, nk, + stack, nargs, + stack + nargs, nk, d, nd, kwdefs, closure, name, qualname); } @@ -4893,11 +4904,20 @@ _PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwarg /* issue #27128: support for keywords will come later */ assert(kwargs == NULL); - if (argdefs == NULL && co->co_argcount == nargs && - co->co_kwonlyargcount == 0 && + if (co->co_kwonlyargcount == 0 && kwargs == NULL && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - return _PyFunction_FastCallNoKw(args, nargs, co, globals); + if (argdefs == NULL && co->co_argcount == nargs) { + return _PyFunction_FastCallNoKw(co, args, nargs, globals); + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + return _PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), + globals); + } } kwdefs = PyFunction_GET_KW_DEFAULTS(func); |