[Python-ideas] RFC: PEP: Specialized functions with guards

Victor Stinner victor.stinner at gmail.com
Mon Jan 11 17:44:15 EST 2016


I discussed this PEP on the #pypy IRC channel. I will try to summarize
the discussion with comments on the PEP directly.

2016-01-08 22:31 GMT+01:00 Victor Stinner <victor.stinner at gmail.com>:
> Add an API to add specialized functions with guards to functions, to
> support static optimizers respecting the Python semantic.

"respecting the Python semantics" is not 100% exact. In fact, my FAT
Python makes suble changes on the "Python semantics". For example,
loop unrolling can completly remove the call the range() function. If
a debugger is executed instruction per instruction, the output is
different on an unrolled loop, since the range() call was removed, and
the loop copy is copied. I should maybe elaborate this point in the
rationale, explain that a compromise must be found between the funny
"in Python, everything is mutable" and performance. But remember that
the whole thing (FAT Python, specialization, etc.) is developed
outside CPython and is fully optional.

> Changes
> =======
>
> * Add two new methods to functions:
>
>   - ``specialize(code, guards: list)``: add specialized
>     function with guard. `code` is a code object (ex:
>     ``func2.__code__``) or any callable object (ex: ``len``).
>     The specialization can be ignored if a guard already fails.

This method doesn't make sense at all in PyPy. The method is specific
to CPython since it relies on guards which have a pure C API (see
below). The PEP must be more explicit about that. IMHO it's perfectly
fine that PyPy makes this method a no-op (the method exactly does
nothing). It's already the case if a guard "always" fail in
first_check().

>   - ``get_specialized()``: get the list of specialized functions with
>     guards

Again, it doesn't make sense for PyPy. Since this method is only used
for unit tests, it can be converted to a function and put somewhere
else, maybe in the _testcapi module.

It's not a good idea to rely on this method in an application, it's
really an implementation detail.

> * Base ``Guard`` type

In fact, exposing the type at the C level is enough. There is no need
to expose it at Python level, since the type has no method nor data,
and it's not possible to use it in Python. We might expose it in a
different module, again, maybe in _testcapi for unit tests.

>   * ``int check(PyObject *guard, PyObject **stack)``: return 1 on
>     success, 0 if the guard failed temporarely, -1 if the guard will
>     always fail

I forgot "int na" and "int nk" parameters to support keywords arguments.

Note for myself: I should add support for raising an exception.

>   * ``int first_check(PyObject *guard, PyObject *func)``: return 0 on
>     success, -1 if the guard will always fail

Note for myself: I should rename the method to "init()" and support
raising an exception.

> Behaviour
> =========
>
> When a function code is replaced (``func.__code__ = new_code``), all
> specialized functions are removed.

Moreover, the PEP must be clear about func.__code__ content:
func.specialize() must *not* modify func.__code__. It should be a
completly black box.

Victor


More information about the Python-ideas mailing list