summaryrefslogtreecommitdiff
path: root/Objects/lnotab_notes.txt
diff options
context:
space:
mode:
authorIvan Levkivskyi <levkivskyi@gmail.com>2017-03-14 20:42:09 +0100
committerSerhiy Storchaka <storchaka@gmail.com>2017-03-14 21:42:09 +0200
commit9135275cba680902e6caf29461f0423dc570190d (patch)
tree6935fdc1a9475248decf9ea2985487ad56645b8c /Objects/lnotab_notes.txt
parent2e4e011795d26cab1a3843383d0539c12fea2458 (diff)
downloadcpython-git-9135275cba680902e6caf29461f0423dc570190d.tar.gz
bpo-28810: Update lnotab_notes.txt (#665)
Diffstat (limited to 'Objects/lnotab_notes.txt')
-rw-r--r--Objects/lnotab_notes.txt50
1 files changed, 28 insertions, 22 deletions
diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt
index 515375772e..3dab2b9866 100644
--- a/Objects/lnotab_notes.txt
+++ b/Objects/lnotab_notes.txt
@@ -1,17 +1,18 @@
All about co_lnotab, the line number table.
Code objects store a field named co_lnotab. This is an array of unsigned bytes
-disguised as a Python string. It is used to map bytecode offsets to source code
-line #s for tracebacks and to identify line number boundaries for line tracing.
+disguised as a Python bytes object. It is used to map bytecode offsets to
+source code line #s for tracebacks and to identify line number boundaries for
+line tracing.
The array is conceptually a compressed list of
(bytecode offset increment, line number increment)
pairs. The details are important and delicate, best illustrated by example:
byte code offset source code line number
- 0 1
- 6 2
- 50 7
+ 0 1
+ 6 2
+ 50 7
350 207
361 208
@@ -24,7 +25,8 @@ look like:
The above doesn't really work, but it's a start. An unsigned byte (byte code
offset) can't hold negative values, or values larger than 255, a signed byte
(line number) can't hold values larger than 127 or less than -128, and the
-above example contains two such values. So we make two tweaks:
+above example contains two such values. (Note that before 3.6, line number
+was also encoded by an unsigned byte.) So we make two tweaks:
(a) there's a deep assumption that byte code offsets increase monotonically,
and
@@ -52,7 +54,7 @@ the example above, assemble_lnotab in compile.c should not (as was actually done
until 2.2) expand 300, 200 to
255, 255, 45, 45,
but to
- 255, 0, 45, 128, 0, 72.
+ 255, 0, 45, 127, 0, 73.
The above is sufficient to reconstruct line numbers for tracebacks, but not for
line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c
@@ -83,30 +85,34 @@ Consider this code:
1: def f(a):
2: while a:
-3: print 1,
+3: print(1)
4: break
5: else:
-6: print 2,
+6: print(2)
which compiles to this:
- 2 0 SETUP_LOOP 19 (to 22)
- >> 3 LOAD_FAST 0 (a)
- 6 POP_JUMP_IF_FALSE 17
+ 2 0 SETUP_LOOP 26 (to 28)
+ >> 2 LOAD_FAST 0 (a)
+ 4 POP_JUMP_IF_FALSE 18
- 3 9 LOAD_CONST 1 (1)
- 12 PRINT_ITEM
+ 3 6 LOAD_GLOBAL 0 (print)
+ 8 LOAD_CONST 1 (1)
+ 10 CALL_FUNCTION 1
+ 12 POP_TOP
- 4 13 BREAK_LOOP
- 14 JUMP_ABSOLUTE 3
- >> 17 POP_BLOCK
+ 4 14 BREAK_LOOP
+ 16 JUMP_ABSOLUTE 2
+ >> 18 POP_BLOCK
- 6 18 LOAD_CONST 2 (2)
- 21 PRINT_ITEM
- >> 22 LOAD_CONST 0 (None)
- 25 RETURN_VALUE
+ 6 20 LOAD_GLOBAL 0 (print)
+ 22 LOAD_CONST 2 (2)
+ 24 CALL_FUNCTION 1
+ 26 POP_TOP
+ >> 28 LOAD_CONST 0 (None)
+ 30 RETURN_VALUE
-If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 17
+If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 18
and the co_lnotab will claim that execution has moved to line 4, which is wrong.
In this case, we could instead associate the POP_BLOCK with line 5, but that
would break jumps around loops without else clauses.