Message32469
Hi Chris,
I have done some digging and it seems the problem is rooted in the way
co_lnotab is constructed for code objects
(http://docs.python.org/ref/types.html#l2h-139).
Consider for example the following code:
> line 0: def loop():
> line 1: while True:
> line 2: pass
Both Python 2.4 and Python 2.5 emit the same disassembly for that code
(using dis.dis()) :
> 1 0 SETUP_LOOP 12 (to 15)
> >> 3 LOAD_GLOBAL 0 (True)
> 6 JUMP_IF_FALSE 4 (to 13)
> 9 POP_TOP
>
> 2 10 JUMP_ABSOLUTE 3
> >> 13 POP_TOP
> 14 POP_BLOCK
> >> 15 LOAD_CONST 0 (None)
> 18 RETURN_VALUE
However there is a difference with the co_lnotab structure between the
versions.
Python 2.4 emits the following offsets:
> byte code offsets: [0, 3, 7]
> source code offsets: [1, 0, 1]
Python 2.5 emits the following offsets for the same code:
> byte code offsets: [0, 10]
> source code offsets: [1, 1]
Note: The above output was generated with the following code:
> print 'byte code offsets: ', [ord(x) for x in
> loop.func_code.co_lnotab[::2]]
> print 'source code offsets:', [ord(x) for x in
> loop.func_code.co_lnotab[1::2]]
So, what happens is that in offset 10, the while loop jumps back with
JUMP_ABSOLUTE 3, but in Python 2.5 that offset is missing from the byte
code offsets in co_lnotab. Python considers only offsets that appear in
that structure for the purpose of tracing, and therefore that line
(source line number 1) is skipped when jumped back to in Python 2.5
co_lnotab is constructed in compile.c but since that file was changed
considerably between Python 2.4 and Python 2.5 I did not try to pinpoint
the source of difference.
In addition I do not know the motivation of this difference. It could be
a mere bug, but it can also be by design, meaning that simply reverting
the co_lnotab construction behavior back might break Python 2.5 elsewhere.
Cheers,
Nir |
|
Date |
User |
Action |
Args |
2007-08-23 14:58:26 | admin | link | issue1750076 messages |
2007-08-23 14:58:26 | admin | create | |
|