Skip to content

Commit 9135275

Browse files
ilevkivskyiserhiy-storchaka
authored andcommitted
bpo-28810: Update lnotab_notes.txt (#665)
1 parent 2e4e011 commit 9135275

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

Objects/lnotab_notes.txt

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
All about co_lnotab, the line number table.
22

33
Code objects store a field named co_lnotab. This is an array of unsigned bytes
4-
disguised as a Python string. It is used to map bytecode offsets to source code
5-
line #s for tracebacks and to identify line number boundaries for line tracing.
4+
disguised as a Python bytes object. It is used to map bytecode offsets to
5+
source code line #s for tracebacks and to identify line number boundaries for
6+
line tracing.
67

78
The array is conceptually a compressed list of
89
(bytecode offset increment, line number increment)
910
pairs. The details are important and delicate, best illustrated by example:
1011

1112
byte code offset source code line number
12-
0 1
13-
6 2
14-
50 7
13+
0 1
14+
6 2
15+
50 7
1516
350 207
1617
361 208
1718

@@ -24,7 +25,8 @@ look like:
2425
The above doesn't really work, but it's a start. An unsigned byte (byte code
2526
offset) can't hold negative values, or values larger than 255, a signed byte
2627
(line number) can't hold values larger than 127 or less than -128, and the
27-
above example contains two such values. So we make two tweaks:
28+
above example contains two such values. (Note that before 3.6, line number
29+
was also encoded by an unsigned byte.) So we make two tweaks:
2830

2931
(a) there's a deep assumption that byte code offsets increase monotonically,
3032
and
@@ -52,7 +54,7 @@ the example above, assemble_lnotab in compile.c should not (as was actually done
5254
until 2.2) expand 300, 200 to
5355
255, 255, 45, 45,
5456
but to
55-
255, 0, 45, 128, 0, 72.
57+
255, 0, 45, 127, 0, 73.
5658

5759
The above is sufficient to reconstruct line numbers for tracebacks, but not for
5860
line tracing. Tracing is handled by PyCode_CheckLineNumber() in codeobject.c
@@ -83,30 +85,34 @@ Consider this code:
8385

8486
1: def f(a):
8587
2: while a:
86-
3: print 1,
88+
3: print(1)
8789
4: break
8890
5: else:
89-
6: print 2,
91+
6: print(2)
9092

9193
which compiles to this:
9294

93-
2 0 SETUP_LOOP 19 (to 22)
94-
>> 3 LOAD_FAST 0 (a)
95-
6 POP_JUMP_IF_FALSE 17
95+
2 0 SETUP_LOOP 26 (to 28)
96+
>> 2 LOAD_FAST 0 (a)
97+
4 POP_JUMP_IF_FALSE 18
9698

97-
3 9 LOAD_CONST 1 (1)
98-
12 PRINT_ITEM
99+
3 6 LOAD_GLOBAL 0 (print)
100+
8 LOAD_CONST 1 (1)
101+
10 CALL_FUNCTION 1
102+
12 POP_TOP
99103

100-
4 13 BREAK_LOOP
101-
14 JUMP_ABSOLUTE 3
102-
>> 17 POP_BLOCK
104+
4 14 BREAK_LOOP
105+
16 JUMP_ABSOLUTE 2
106+
>> 18 POP_BLOCK
103107

104-
6 18 LOAD_CONST 2 (2)
105-
21 PRINT_ITEM
106-
>> 22 LOAD_CONST 0 (None)
107-
25 RETURN_VALUE
108+
6 20 LOAD_GLOBAL 0 (print)
109+
22 LOAD_CONST 2 (2)
110+
24 CALL_FUNCTION 1
111+
26 POP_TOP
112+
>> 28 LOAD_CONST 0 (None)
113+
30 RETURN_VALUE
108114

109-
If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 17
115+
If 'a' is false, execution will jump to the POP_BLOCK instruction at offset 18
110116
and the co_lnotab will claim that execution has moved to line 4, which is wrong.
111117
In this case, we could instead associate the POP_BLOCK with line 5, but that
112118
would break jumps around loops without else clauses.

0 commit comments

Comments
 (0)