
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@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