I'm not the world's leading expert on Python bytecode anymore, but unless
there's something I'm missing your conclusion looks eminently reasonable,
and so I expect you'll get very little traction on this thread. (If you had
wanted to get a megathread you should have written "FASTCALL considered
harmful". :-)

I think there was one person in another thread (INADA Naoki?) who thought
METH_FASTCALL could use improvements. Maybe that person can write back to
this thread? Or perhaps Victor Stinner (who seems to have touched it last)
has a suggestion for what could be improved about it?

--Guido

On Thu, Jul 5, 2018 at 7:55 AM Jeroen Demeyer <j.deme...@ugent.be> wrote:

> Hello all,
>
> As discussed in some other threads ([1], [2]), we should discuss the
> METH_FASTCALL calling convention.
>
> For passing only positional arguments, a C array of Python objects is
> used, which is as fast as it can get. When the Python interpreter calls
> a function, it builds that C array on the interpreter stack:
>
>  >>> from dis import dis
>  >>> def f(x, y): return g(x, y, 12)
>  >>> dis(f)
>    1           0 LOAD_GLOBAL              0 (g)
>                2 LOAD_FAST                0 (x)
>                4 LOAD_FAST                1 (y)
>                6 LOAD_CONST               1 (12)
>                8 CALL_FUNCTION            3
>               10 RETURN_VALUE
>
> A C array can also easily and efficiently be handled by the C function
> receiving it. So I consider this uncontroversial.
>
> The convention for METH_FASTCALL|METH_KEYWORDS is that keyword *names*
> are passed as a tuple and keyword *values* in the same C array with
> positional arguments. An example:
>
>  >>> from dis import dis
>  >>> def f(x, y, z): return f(x, foo=y, bar=z)
>  >>> dis(f)
>    1           0 LOAD_GLOBAL              0 (f)
>                2 LOAD_FAST                0 (x)
>                4 LOAD_FAST                1 (y)
>                6 LOAD_FAST                2 (z)
>                8 LOAD_CONST               1 (('foo', 'bar'))
>               10 CALL_FUNCTION_KW         3
>               12 RETURN_VALUE
>
> This is pretty clever: it exploits the fact that ('foo', 'bar') is a
> constant tuple stored in f.__code__.co_consts. Also, a tuple can be
> efficiently handled by the called code: it is essentially a thin wrapper
> around a C array of Python objects. So this works well.
>
> The only case when this handling of keywords is suboptimal is when using
> **kwargs. In that case, a dict must be converted to a tuple. It looks
> hard to me to support efficiently both the case of fixed keyword
> arguments (f(foo=x)) and a keyword dict (f(**kwargs)). Since the former
> is more common than the latter, the current choice is optimal.
>
> 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.
>
>
> Jeroen.
>
>
> [1] https://mail.python.org/pipermail/python-dev/2018-June/153945.html
> [2] https://mail.python.org/pipermail/python-dev/2018-July/154251.html
> _______________________________________________
> 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/guido%40python.org
>


-- 
--Guido van Rossum (python.org/~guido)
_______________________________________________
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