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 gain.

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.

_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to