On 11/9/2015 9:37 PM, Steven D'Aprano wrote:

The compiler doesn't need to decide *in advance* whether the attribute might
have changed. It knows whether it has changed or not *at runtime*.

You are using 'compiler' when you should, to avoid confusion, use 'interpreter'.

It's one thing to say that *in principle* any function might modify or
shadow builtins. That's true, because we don't know what's inside the
function. But the compiler knows, because it actually executes the code

'interpreter'

inside the function and can see what happens when it does. It doesn't have
to predict in advance whether or not calling `func(x)` shadows the builtin
`len` function, *it can see for itself* whether it did or not.

At compile time, `func(x)` might do anything. But at runtime, we know
exactly what it did, because it just did it.

Imagine that the compiler keeps track of whether or not builtins has been

/compiler/code compiled by the compiler and interpreted by the interpreter (which could be the CPU)/

modified. Think of it as a simple "dirty" flag that says "yes, builtins is
still pristine" or "no, something may have shadowed or modified the
builtins". That's fairly straight-forward: builtins is a dict, and the
compiler can tell whether or not __setitem__ etc has been called on that
dict. Likewise, it can keep track of whether or not a global has been
created that shadows builtins: some of that can be done statically, at
compile-time, but most of it needs to be done dynamically, at runtime.

This is more or less Victor Stinner's proposal, and he has a working prototype that runs nearly all the test suite. He now plans to refine it and measure changes in space and time usage.

If the flag is set, the compiler knows that the optimization is unsafe and
it has to follow the standard name lookup, and you lose nothing: the
standard Python semantics are still followed. But if the flag is clear, the
compiler knows that nothing has shadowed or modified builtins, and a whole
class of optimizations are safe. It can replace a call to (say) len(x) with
a fast jump, avoiding an unnecessary name lookup in globals, and another
unnecessary name lookup in builtins. Or it might even inline the call to
len. Since *most* code doesn't play tricks with builtins, the overhead of
tracking these changes pays off *most* of the time -- and when it doesn't,
the penalty is very small.


--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to