_PyFunction_FastCallDict() supports keyword args

Issue #27809:

* Rename _PyFunction_FastCall() to _PyFunction_FastCallDict()
* Rename _PyCFunction_FastCall() to _PyCFunction_FastCallDict()
*  _PyFunction_FastCallDict() now supports keyword arguments
This commit is contained in:
Victor Stinner 2016-08-22 23:15:44 +02:00
parent 559bb6a713
commit b900939186
5 changed files with 51 additions and 20 deletions

View File

@ -59,7 +59,7 @@ PyAPI_FUNC(PyObject *) PyFunction_GetAnnotations(PyObject *);
PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *); PyAPI_FUNC(int) PyFunction_SetAnnotations(PyObject *, PyObject *);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyFunction_FastCall( PyAPI_FUNC(PyObject *) _PyFunction_FastCallDict(
PyObject *func, PyObject *func,
PyObject **args, int nargs, PyObject **args, int nargs,
PyObject *kwargs); PyObject *kwargs);

View File

@ -38,7 +38,7 @@ PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *);
PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyCFunction_Call(PyObject *, PyObject *, PyObject *);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyCFunction_FastCall(PyObject *func, PyAPI_FUNC(PyObject *) _PyCFunction_FastCallDict(PyObject *func,
PyObject **args, int nargs, PyObject **args, int nargs,
PyObject *kwargs); PyObject *kwargs);
#endif #endif

View File

@ -2255,7 +2255,8 @@ _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
} }
PyObject * PyObject *
_PyObject_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) _PyObject_FastCallDict(PyObject *func, PyObject **args, int nargs,
PyObject *kwargs)
{ {
ternaryfunc call; ternaryfunc call;
PyObject *result = NULL; PyObject *result = NULL;
@ -2268,19 +2269,17 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, int nargs, PyObject *kwa
assert(func != NULL); assert(func != NULL);
assert(nargs >= 0); assert(nargs >= 0);
assert(nargs == 0 || args != NULL); assert(nargs == 0 || args != NULL);
/* issue #27128: support for keywords will come later: assert(kwargs == NULL || PyDict_Check(kwargs));
_PyFunction_FastCall() doesn't support keyword arguments yet */
assert(kwargs == NULL);
if (Py_EnterRecursiveCall(" while calling a Python object")) { if (Py_EnterRecursiveCall(" while calling a Python object")) {
return NULL; return NULL;
} }
if (PyFunction_Check(func)) { if (PyFunction_Check(func)) {
result = _PyFunction_FastCall(func, args, nargs, kwargs); result = _PyFunction_FastCallDict(func, args, nargs, kwargs);
} }
else if (PyCFunction_Check(func)) { else if (PyCFunction_Check(func)) {
result = _PyCFunction_FastCall(func, args, nargs, kwargs); result = _PyCFunction_FastCallDict(func, args, nargs, kwargs);
} }
else { else {
PyObject *tuple; PyObject *tuple;

View File

@ -146,8 +146,8 @@ PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
} }
PyObject * PyObject *
_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, int nargs, _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, int nargs,
PyObject *kwargs) PyObject *kwargs)
{ {
PyCFunctionObject* func = (PyCFunctionObject*)func_obj; PyCFunctionObject* func = (PyCFunctionObject*)func_obj;
PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyCFunction meth = PyCFunction_GET_FUNCTION(func);
@ -155,7 +155,7 @@ _PyCFunction_FastCall(PyObject *func_obj, PyObject **args, int nargs,
PyObject *result; PyObject *result;
int flags; int flags;
/* _PyCFunction_FastCall() must not be called with an exception set, /* _PyCFunction_FastCallDict() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the because it may clear it (directly or indirectly) and so the
caller loses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!PyErr_Occurred());

View File

@ -4889,24 +4889,29 @@ fast_function(PyObject *func, PyObject **stack, int n, int nargs, int nk)
} }
PyObject * PyObject *
_PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwargs) _PyFunction_FastCallDict(PyObject *func, PyObject **args, int nargs,
PyObject *kwargs)
{ {
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
PyObject *kwdefs, *closure, *name, *qualname; PyObject *kwdefs, *closure, *name, *qualname;
PyObject *kwtuple, **k;
PyObject **d; PyObject **d;
int nd; int nd;
Py_ssize_t nk;
PyObject *result;
PCALL(PCALL_FUNCTION); PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION); PCALL(PCALL_FAST_FUNCTION);
/* issue #27128: support for keywords will come later */ assert(kwargs == NULL || PyDict_Check(kwargs));
assert(kwargs == NULL);
if (co->co_kwonlyargcount == 0 && kwargs == NULL && if (co->co_kwonlyargcount == 0 &&
(kwargs == NULL || PyDict_Size(kwargs) == 0) &&
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
{ {
/* Fast paths */
if (argdefs == NULL && co->co_argcount == nargs) { if (argdefs == NULL && co->co_argcount == nargs) {
return _PyFunction_FastCallNoKw(co, args, nargs, globals); return _PyFunction_FastCallNoKw(co, args, nargs, globals);
} }
@ -4920,6 +4925,30 @@ _PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwarg
} }
} }
if (kwargs != NULL) {
Py_ssize_t pos, i;
nk = PyDict_Size(kwargs);
kwtuple = PyTuple_New(2 * nk);
if (kwtuple == NULL) {
return NULL;
}
k = &PyTuple_GET_ITEM(kwtuple, 0);
pos = i = 0;
while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) {
Py_INCREF(k[i]);
Py_INCREF(k[i+1]);
i += 2;
}
nk = i / 2;
}
else {
kwtuple = NULL;
k = NULL;
nk = 0;
}
kwdefs = PyFunction_GET_KW_DEFAULTS(func); kwdefs = PyFunction_GET_KW_DEFAULTS(func);
closure = PyFunction_GET_CLOSURE(func); closure = PyFunction_GET_CLOSURE(func);
name = ((PyFunctionObject *)func) -> func_name; name = ((PyFunctionObject *)func) -> func_name;
@ -4933,11 +4962,14 @@ _PyFunction_FastCall(PyObject *func, PyObject **args, int nargs, PyObject *kwarg
d = NULL; d = NULL;
nd = 0; nd = 0;
} }
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
args, nargs, result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
NULL, 0, args, nargs,
d, nd, kwdefs, k, (int)nk,
closure, name, qualname); d, nd, kwdefs,
closure, name, qualname);
Py_XDECREF(kwtuple);
return result;
} }
static PyObject * static PyObject *