[Python-Dev] On the METH_FASTCALL calling convention
storchaka at gmail.com
Sat Jul 7 04:55:22 EDT 2018
05.07.18 17:53, Jeroen Demeyer пише:
> In other words: I see nothing to improve in the calling convention of
> METH_FASTCALL. I suggest to keep it and make it public as-is.
You have considered the bytecode for calling functions, but this
actually is not directly related to the calling convention. All opcodes
(CALL_FUNCTION, CALL_FUNCTION_KW, CALL_FUNCTION_EX and CALL_METHOD) can
be used for calling any callable. CALL_FUNCTION, CALL_FUNCTION_KW was
designed for reducing the overhead from the caller side for most common
cases, and CALL_FUNCTION_EX is used for the rest.
Calling conventions METH_FASTCALL and METH_FASTCALL|METH_KEYWORDS was
designed for reducing the overhead of creating a temporary tuple and
dict. They allow to avoid allocation and copying in case of using
opcodes CALL_FUNCTION, CALL_FUNCTION_KW and in most cases of using C API
for calling function. But it is not the only possible way, there some
details can be changed without performance loss, and may be even with a
After passing positional and keyword arguments to the C function, we
need to convert Python objects to C values. For positional-only
parameters we can use PyArg_ParseTuple() (for METH_VARARGS) and
_PyArg_ParseStack() (for METH_FASTCALL). If there are keyword
parameters, we need to use more complicated API:
PyArg_ParseTupleAndKeywords() or private
_PyArg_ParseTupleAndKeywordsFast() (for METH_VARARGS|METH_KEYWORDS) and
private _PyArg_ParseStackAndKeywords() (for
METH_FASTCALL|METH_KEYWORDS). _PyArg_ParseTupleAndKeywordsFast() and
_PyArg_ParseStackAndKeywords() are private, complex, unstable and can be
used only internally in CPython (mostly in the code generated by
Argument Clinic). They have complex signatures and their code is mostly
duplicate one other (but with some important differences).
There is a wish of inlining argument parsing functions in the Argument
Clinic generated code. It is easier to do for PyArg_ParseTuple() and
_PyArg_UnpackStack(). But functions for parsing keyword arguments are
more complex, because they perform two things: match keyword argument
names to parameter positions and convert argument values to C.
There is my idea. Split every of keyword argument parsing functions on
two parts. The first part linearize keyword arguments, it converts
positional and keyword arguments (in whatever form they were presented)
into a linear array of PyObject* (with NULLs for not specified optional
arguments). The second part is common and similar to
_PyArg_ParseStack(), but supports NULLs. It converts an array of
PyObject* to a sequence of C values. I tried to implement this idea, is
is not simple, and results were mixed, but I don't loss a hope.
And here we return to METH_FASTCALL|METH_KEYWORDS. The first part of
handling arguments can be made outside of the C function, by the calling
API. Then the signature of the C function can be simpler, the same as
for METH_FASTCALL. But we need to expose the list of keyword parameter
names as an attribute of CFunction.
I don't know whether this ides is vital or dead, but I' going to try it.
And implementing it will change the METH_FASTCALL|METH_KEYWORDS calling
convention a lot.
More information about the Python-Dev