On 04/01/2011 01:02, Guido van Rossum wrote:
On Mon, Jan 3, 2011 at 9:52 AM, David Malcolmdmalcolm@redhat.com wrote:
On Sun, 2011-01-02 at 19:18 -0800, Guido van Rossum wrote:
On Sun, Jan 2, 2011 at 5:50 PM, Alex Gaynoralex.firstname.lastname@example.org wrote:
No, it's singularly impossible to prove that any global load will be any given value at compile time. Any optimization based on this premise is wrong.
My proposed way out of this conundrum has been to change the language semantics slightly so that global names which (a) coincide with a builtin, and (b) have no explicit assignment to them in the current module, would be fair game for such optimizations, with the understanding that the presence of e.g. "len = len" anywhere in the module (even in dead code!) would be sufficient to disable the optimization.
But barring someone interested in implementing something based on this rule, the proposal has languished for many years.
Is there a PEP for this?
Not that I know of, otherwise I'd have mentioned it. :-)
It would be useful if someone wrote it up, since the idea comes back in one form or another regularly.
FWIW, this is reminiscent of Fortran's rules for "intrinsics" (its name for builtins), which have a similar optimization behavior (except there the potential overrides that the compiler doesn't need to take into account are load-time definitions).
I've been attempting another way in: http://bugs.python.org/issue10399 using a new "JUMP_IF_SPECIALIZABLE" opcode. This compares what a value is against a compile-time prediction, branching to an optimized implementation if the guess was correct. I use this to implement function-call inlining within the generated bytecode.
Yeah, that's what everybody proposes to keep the language semantics unchanged. But I claim that an easier solution is to say to hell with those semantics, let's change them to make the implementation simpler. That's from the Zen of Python: "If the implementation is easy to explain, it may be a good idea." I guess few people can seriously propose to change Python's semantics, that's why *I* am proposing it. :-) Note that the semantics of locals (e.g. UnboundLocalError) were also changed specifically to allow a significant optimization -- again by me.
I think someone else pointed this out, but replacing builtins externally to a module is actually common for testing. In particular replacing the open function, but also other builtins, is often done temporarily to replace it with a mock. It seems like this optimisation would break those tests.
Caveat-of-doom: That code's very much a work-in-progress at this stage, though: sometimes it doesn't segfault :) and the way that I track the predicted values is taking some other liberties with semantics (see that URL and the dmalcolm-ast-optimization-branch in SVN).
(There's probably at least 2 PEPs in the above idea, though have yet to write my first PEP)
If you want to write up a PEP for the semantics change I am proposing, everything you need is in this thread.