return result;
}
+static PyObject *
+_PyStack_AsDict(PyObject **values, Py_ssize_t nkwargs, PyObject *kwnames,
+ PyObject *func)
+{
+ PyObject *kwdict;
+ Py_ssize_t i;
+
+ kwdict = PyDict_New();
+ if (kwdict == NULL) {
+ return NULL;
+ }
+
+ for (i=0; i < nkwargs; i++) {
+ int err;
+ PyObject *key = PyTuple_GET_ITEM(kwnames, i);
+ PyObject *value = *values++;
+
+ if (PyDict_GetItem(kwdict, key) != NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s%s got multiple values "
+ "for keyword argument '%U'",
+ PyEval_GetFuncName(func),
+ PyEval_GetFuncDesc(func),
+ key);
+ Py_DECREF(kwdict);
+ return NULL;
+ }
+
+ err = PyDict_SetItem(kwdict, key, value);
+ if (err) {
+ Py_DECREF(kwdict);
+ return NULL;
+ }
+ }
+ return kwdict;
+}
+
+PyObject *
+_PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
+ PyObject *kwnames)
+{
+ PyObject *kwdict, *result;
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+
+ assert(nargs >= 0);
+ assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
+ assert((nargs == 0 && nkwargs == 0) || stack != NULL);
+
+ if (PyFunction_Check(func)) {
+ /* Fast-path: avoid temporary tuple or dict */
+ return _PyFunction_FastCallKeywords(func, stack, nargs, kwnames);
+ }
+
+ if (nkwargs > 0) {
+ kwdict = _PyStack_AsDict(stack + nargs, nkwargs, kwnames, func);
+ if (kwdict == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ kwdict = NULL;
+ }
+
+ result = _PyObject_FastCallDict(func, stack, nargs, kwdict);
+ Py_XDECREF(kwdict);
+ return result;
+}
+
static PyObject*
call_function_tail(PyObject *callable, PyObject *args)
{
#else
static PyObject * call_function(PyObject ***, Py_ssize_t, PyObject *);
#endif
-static PyObject * fast_function(PyObject *, PyObject ***, Py_ssize_t, PyObject *);
-static PyObject * do_call(PyObject *, PyObject ***, Py_ssize_t, PyObject *);
+static PyObject * fast_function(PyObject *, PyObject **, Py_ssize_t, PyObject *);
static PyObject * do_call_core(PyObject *, PyObject *, PyObject *);
static PyObject * create_keyword_args(PyObject *, PyObject ***, PyObject *);
static PyObject * load_args(PyObject ***, Py_ssize_t);
}
static PyObject *
-call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *names
+call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames
#ifdef WITH_TSC
, uint64* pintr0, uint64* pintr1
#endif
PyObject **pfunc = (*pp_stack) - oparg - 1;
PyObject *func = *pfunc;
PyObject *x, *w;
- Py_ssize_t nk = names == NULL ? 0 : PyTuple_GET_SIZE(names);
- Py_ssize_t nargs = oparg - nk;
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+ Py_ssize_t nargs = oparg - nkwargs;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION);
- if (names == NULL && flags & (METH_NOARGS | METH_O)) {
+ if (kwnames == NULL && flags & (METH_NOARGS | METH_O)) {
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
if (flags & METH_NOARGS && nargs == 0) {
}
else {
PyObject *callargs, *kwdict = NULL;
- if (names != NULL) {
- kwdict = create_keyword_args(names, pp_stack, func);
+ if (kwnames != NULL) {
+ kwdict = create_keyword_args(kwnames, pp_stack, func);
if (kwdict == NULL) {
x = NULL;
goto cfuncerror;
}
}
else {
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+ PyObject **stack;
+
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
/* optimize access to bound methods */
PyObject *self = PyMethod_GET_SELF(func);
Py_INCREF(func);
}
+ stack = (*pp_stack) - nargs - nkwargs;
+
READ_TIMESTAMP(*pintr0);
if (PyFunction_Check(func)) {
- x = fast_function(func, pp_stack, nargs, names);
- } else {
- x = do_call(func, pp_stack, nargs, names);
+ x = fast_function(func, stack, nargs, kwnames);
+ }
+ else {
+ x = _PyObject_FastCallKeywords(func, stack, nargs, kwnames);
}
READ_TIMESTAMP(*pintr1);
*/
static PyObject*
-_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
- PyObject *globals)
+_PyFunction_FastCall(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
+ PyObject *globals)
{
PyFrameObject *f;
PyThreadState *tstate = PyThreadState_GET();
return result;
}
-/* Similar to _PyFunction_FastCall() but keywords are passed a (key, value)
- pairs in stack */
static PyObject *
-fast_function(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, PyObject *names)
+fast_function(PyObject *func, PyObject **stack,
+ Py_ssize_t nargs, PyObject *kwnames)
{
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
PyObject *kwdefs, *closure, *name, *qualname;
PyObject **d;
- Py_ssize_t nkwargs = names == NULL ? 0 : PyTuple_GET_SIZE(names);
+ Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
Py_ssize_t nd;
- PyObject **stack = (*pp_stack)-nargs-nkwargs;
+
+ assert((nargs == 0 && nkwargs == 0) || stack != NULL);
PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION);
co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
{
if (argdefs == NULL && co->co_argcount == nargs) {
- return _PyFunction_FastCallNoKw(co, stack, nargs, globals);
+ return _PyFunction_FastCall(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);
+ return _PyFunction_FastCall(co, stack, Py_SIZE(argdefs), globals);
}
}
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
stack, nargs,
NULL, 0,
- names, stack + nargs,
+ kwnames, stack + nargs,
d, (int)nd, kwdefs,
closure, name, qualname);
}
+PyObject *
+_PyFunction_FastCallKeywords(PyObject *func, PyObject **stack,
+ Py_ssize_t nargs, PyObject *kwnames)
+{
+ return fast_function(func, stack, nargs, kwnames);
+}
+
PyObject *
_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
PyObject *kwargs)
{
/* Fast paths */
if (argdefs == NULL && co->co_argcount == nargs) {
- return _PyFunction_FastCallNoKw(co, args, nargs, globals);
+ return _PyFunction_FastCall(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);
+ return _PyFunction_FastCall(co, args, Py_SIZE(argdefs), globals);
}
}
return NULL;
while (--nk >= 0) {
int err;
- PyObject *value = EXT_POP(*pp_stack);
PyObject *key = PyTuple_GET_ITEM(names, nk);
+ PyObject *value = EXT_POP(*pp_stack);
if (PyDict_GetItem(kwdict, key) != NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s%s got multiple values "
return args;
}
-static PyObject *
-do_call(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, PyObject *kwnames)
-{
- PyObject *callargs, *kwdict, *result;
-
- if (kwnames != NULL) {
- kwdict = create_keyword_args(kwnames, pp_stack, func);
- if (kwdict == NULL) {
- return NULL;
- }
- }
- else {
- kwdict = NULL;
- }
-
- callargs = load_args(pp_stack, nargs);
- if (callargs == NULL) {
- Py_XDECREF(kwdict);
- return NULL;
- }
-
- result = do_call_core(func, callargs, kwdict);
- Py_XDECREF(callargs);
- Py_XDECREF(kwdict);
- return result;
-}
-
static PyObject *
do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
{