Issue #27809: partial_call() uses fast call for positional args

This commit is contained in:
Victor Stinner 2016-08-23 16:22:35 +02:00
parent 1fa6915427
commit f4d28d4385
1 changed files with 28 additions and 12 deletions

View File

@ -128,44 +128,60 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kw)
{ {
PyObject *ret; PyObject *ret;
PyObject *argappl, *kwappl; PyObject *argappl, *kwappl;
PyObject **stack;
Py_ssize_t nargs;
assert (PyCallable_Check(pto->fn)); assert (PyCallable_Check(pto->fn));
assert (PyTuple_Check(pto->args)); assert (PyTuple_Check(pto->args));
assert (PyDict_Check(pto->kw)); assert (PyDict_Check(pto->kw));
if (PyTuple_GET_SIZE(pto->args) == 0) { if (PyTuple_GET_SIZE(pto->args) == 0) {
argappl = args; stack = &PyTuple_GET_ITEM(args, 0);
Py_INCREF(args); nargs = PyTuple_GET_SIZE(args);
} else if (PyTuple_GET_SIZE(args) == 0) { argappl = NULL;
argappl = pto->args; }
Py_INCREF(pto->args); else if (PyTuple_GET_SIZE(args) == 0) {
} else { stack = &PyTuple_GET_ITEM(pto->args, 0);
nargs = PyTuple_GET_SIZE(pto->args);
argappl = NULL;
}
else {
stack = NULL;
argappl = PySequence_Concat(pto->args, args); argappl = PySequence_Concat(pto->args, args);
if (argappl == NULL) if (argappl == NULL) {
return NULL; return NULL;
}
assert(PyTuple_Check(argappl)); assert(PyTuple_Check(argappl));
} }
if (PyDict_Size(pto->kw) == 0) { if (PyDict_Size(pto->kw) == 0) {
kwappl = kw; kwappl = kw;
Py_XINCREF(kwappl); Py_XINCREF(kwappl);
} else { }
else {
kwappl = PyDict_Copy(pto->kw); kwappl = PyDict_Copy(pto->kw);
if (kwappl == NULL) { if (kwappl == NULL) {
Py_DECREF(argappl); Py_XDECREF(argappl);
return NULL; return NULL;
} }
if (kw != NULL) { if (kw != NULL) {
if (PyDict_Merge(kwappl, kw, 1) != 0) { if (PyDict_Merge(kwappl, kw, 1) != 0) {
Py_DECREF(argappl); Py_XDECREF(argappl);
Py_DECREF(kwappl); Py_DECREF(kwappl);
return NULL; return NULL;
} }
} }
} }
ret = PyObject_Call(pto->fn, argappl, kwappl); if (stack) {
Py_DECREF(argappl); ret = _PyObject_FastCallDict(pto->fn, stack, nargs, kwappl);
}
else {
ret = PyObject_Call(pto->fn, argappl, kwappl);
Py_DECREF(argappl);
}
Py_XDECREF(kwappl); Py_XDECREF(kwappl);
return ret; return ret;
} }