[Python-Dev] Reordering opcodes (PEP 203 Augmented Assignment)

Vladimir Marangozov Vladimir.Marangozov@inrialpes.fr
Mon, 31 Jul 2000 04:34:08 +0200 (CEST)

Mark Hammond wrote:
> > Can someone summarise what the issues are with SET_LINENO?
> > I had the impression that they're not needed for finding the
> > line numbers in tracebacks. So what would we lose if they
> > disappeared?
> The debugger (and quite possibly the profiler - I havent checked!)

Addendum: the debugger in its current state.

And the whole point of the solution we were thinking of is to make sure
that the debugger (and other objects, like tracebacks) do read the line
number only when the main loop fires a "line" event via a hook.

Given the state of the art, however, nobody can guarantee that the
line number is not fetched in legacy code from the frame directly,
through f.lineno (for whatever purpose).

Note that we can trap the access to the f.lineno attribute in
frameobject.c, but the problem boils down to computing the line number
from the current instruction, i.e. from 'f.lasti', because the only
thing we have at our disposal is a table (co_lnotab) which maps
line number offsets and instruction offsets (through delta increments).

Note that the f.lasti attr is not updated as it should in the main loop,
because it would infer a lot of overhead (to be up to date, it needs to
be updated for every opcode). It is updated only for 'important' events:
a trace hook, an exception, a Python function call.

So, at the heart of the difficulty here is the fact that we can't figure
out precisely where we are in the opcode stream, if we ask that from
Python (because the program counter is not stored anywhere regularly).
We need to get notified by the main loop.

And whenever you ask 'f.lineno' from Python, well, you're asking this
information from the Python side (without notification from the C side). 

Do you follow me up to this point? :-)

Now, with SET_LINENO, we are sure that f.lineno is always up to date,
because its purpose is to update f.lineno (on one hand) *and* to fire
a "line" event from the main loop if a hook is in place. The compiler
makes sure to insert SET_LINENO opcodes for each new source line
(this is why, BTW, you can end up with 10 SET_LINENO in a row if you
have 10 doc strings in a row that describe some Python function).

Without SET_LINENO, we have to deal with these two problems: firing
"line" events whenever a tracing function is set and updating f.lineno.
We can manage to fire a "line" event (through the scheme I've explained
previously, or similar), but we still can't (well, I don't see a reliable
way so far) update f.lineno permanently.

that's-all-<wink>'ly y'rs
       Vladimir MARANGOZOV          | Vladimir.Marangozov@inrialpes.fr
http://sirac.inrialpes.fr/~marangoz | tel:(+33-4)76615277 fax:76615252