_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:
parent
559bb6a713
commit
b900939186
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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 *
|
||||||
|
|
Loading…
Reference in New Issue