GeezerVison is showing github.com — Change dis output to display labels instead of offsets · Issue #112137 · python/cpython
Change dis output to display labels instead of offsets #112137DescriptionTODO:
- test for output with offsets
-
-- instead of None for missing line number? - in another PR.
Feature or enhancement
>>> def f():
... for i in x:
... if y:
... z
...
>>> dis.dis(f)
1 RESUME 0
2 LOAD_GLOBAL 0 (x)
GET_ITER
L1: FOR_ITER 22 (to L3)
STORE_FAST 0 (i)
3 LOAD_GLOBAL 2 (y)
TO_BOOL
POP_JUMP_IF_TRUE 2 (to L2)
JUMP_BACKWARD 16 (to L1)
4 L2: LOAD_GLOBAL 4 (z)
POP_TOP
JUMP_BACKWARD 24 (to L1)
2 L3: END_FOR
RETURN_CONST 0 (None)
This is easier to read than the current output of:
>>> dis.dis(f)
1 0 RESUME 0
2 2 LOAD_GLOBAL 0 (x)
12 GET_ITER
>> 14 FOR_ITER 22 (to 62)
18 STORE_FAST 0 (i)
3 20 LOAD_GLOBAL 2 (y)
30 TO_BOOL
38 POP_JUMP_IF_TRUE 2 (to 46)
42 JUMP_BACKWARD 16 (to 14)
4 >> 46 LOAD_GLOBAL 4 (z)
56 POP_TOP
58 JUMP_BACKWARD 24 (to 14)
2 >> 62 END_FOR
64 RETURN_CONST 0 (None)
Linked PRs
Reacted by fastfingertips Activityiritkatriel commented on Nov 16, 2023 More ideas:
- Distinguish between labels which are jump targets (Jx) vs exception handlers (Hx).
- Show the start and end of exception ranges (instead of printing the exception table).
For example:
0 RESUME 0
2 LOAD_NAME 0 (z)
TO_BOOL
POP_JUMP_IF_FALSE 4 (to J1)
3 NOP
H2
| 4 LOAD_NAME 1 (x)
| POP_TOP
-
RETURN_CONST 0 (None)
2 J1: RETURN_CONST 0 (None)
H4
| None H2: PUSH_EXC_INFO
|
| 5 LOAD_NAME 2 (Exception)
| CHECK_EXC_MATCH
| POP_JUMP_IF_FALSE 5 (to J3)
| POP_TOP
|
| 6 LOAD_NAME 3 (y)
| POP_TOP
-
POP_EXCEPT
RETURN_CONST 0 (None)
H4
| 5 J3: RERAISE 0
-
None H4: COPY 3
POP_EXCEPT
RERAISE 1
For this code:
if z:
try:
x
except Exception:
y
markshannon commented on Nov 17, 2023 In theory a disassembler should produce "assembly code" that is a human writable form of the underlying (virtual) machine code.
I don't think I would want to add those vertical bars by hand.
Would start and end labels work? Like this:
0 RESUME 0
2 LOAD_NAME 0 (z)
TO_BOOL
POP_JUMP_IF_FALSE 4 (to j1)
3 NOP
4 h1: LOAD_NAME 1 (x)
h2: POP_TOP
RETURN_CONST 0 (None)
2 j1: RETURN_CONST 0 (None)
None h3: PUSH_EXC_INFO
5 LOAD_NAME 2 (Exception)
CHECK_EXC_MATCH
POP_JUMP_IF_FALSE 5 (to j3)
POP_TOP
6 LOAD_NAME 3 (y)
h4: POP_TOP
POP_EXCEPT
RETURN_CONST 0 (None)
5 j3: RERAISE 0
None h5: COPY 3
POP_EXCEPT
RERAISE 1
ExceptionTable:
h1 to h2 -> h3 [0]
h3 to h4 -> h5 [1] lasti
j3 to j3 -> h5 [1] lasti
markshannon commented on Nov 17, 2023 Since a label can appear as a jump target and in the exception table, maybe just use l1, etc instead of j1 and h1?
Also, do we want labels to the left or right of line numbers, and do we want them on their own lines or on the same line?
If we have them on their own lines, it uses more vertical space, but less width, which is easier to read:
...
h1:
4 LOAD_NAME 1 (x)
h2:
POP_TOP
RETURN_CONST 0 (None)
j1:
2 RETURN_CONST 0 (None)
...
iritkatriel commented on Nov 17, 2023 I have this now:
0 RESUME 0
2 LOAD_NAME 0 (z)
TO_BOOL
POP_JUMP_IF_FALSE 4 (to L3)
3 NOP
L1:
4 LOAD_NAME 1 (x)
POP_TOP
L2:
RETURN_CONST 0 (None)
L3:
2 RETURN_CONST 0 (None)
L4:
None PUSH_EXC_INFO
5 LOAD_NAME 2 (Exception)
CHECK_EXC_MATCH
POP_JUMP_IF_FALSE 5 (to L6)
POP_TOP
6 LOAD_NAME 3 (y)
POP_TOP
L5:
POP_EXCEPT
RETURN_CONST 0 (None)
L6:
5 RERAISE 0
L7:
None COPY 3
POP_EXCEPT
RERAISE 1
ExceptionTable:
L1 to L2 -> L4 [0]
L4 to L5 -> L7 [1] lasti
L6 to L7 -> L7 [1] lasti
iritkatriel commented on Nov 21, 2023 New version with labels not on their own line, and an option to include offsets:
iritkatriel@Irits-MBP cpython % cat xx.py
if a:
try:
1/0
except:
pass
iritkatriel@Irits-MBP cpython % ./python.exe -m dis xx.py
0 RESUME 0
2 LOAD_NAME 0 (a)
TO_BOOL
POP_JUMP_IF_FALSE 7 (to L3)
3 NOP
L1: 4 LOAD_CONST 0 (1)
LOAD_CONST 1 (0)
BINARY_OP 11 (/)
POP_TOP
L2: RETURN_CONST 2 (None)
L3: 2 RETURN_CONST 2 (None)
L4: None PUSH_EXC_INFO
5 POP_TOP
L5: 6 POP_EXCEPT
RETURN_CONST 2 (None)
L6: None COPY 3
POP_EXCEPT
RERAISE 1
ExceptionTable:
L1 to L2 -> L4 [0]
L4 to L5 -> L6 [1] lasti
iritkatriel@Irits-MBP cpython % ./python.exe -m dis -O xx.py
0 0 RESUME 0
2 2 LOAD_NAME 0 (a)
4 TO_BOOL
12 POP_JUMP_IF_FALSE 7 (to L3)
3 16 NOP
L1: 4 18 LOAD_CONST 0 (1)
20 LOAD_CONST 1 (0)
22 BINARY_OP 11 (/)
26 POP_TOP
L2: 28 RETURN_CONST 2 (None)
L3: 2 30 RETURN_CONST 2 (None)
L4: None 32 PUSH_EXC_INFO
5 34 POP_TOP
L5: 6 36 POP_EXCEPT
38 RETURN_CONST 2 (None)
L6: None 40 COPY 3
42 POP_EXCEPT
44 RERAISE 1
ExceptionTable:
L1 to L2 -> L4 [0]
L4 to L5 -> L6 [1] lasti
iritkatriel commented on Nov 21, 2023 I think it would be nice to have -- instead of None for no line number. Reacted by Michael Droettboom, Guido van Rossum, Brandt Bucher and Eric Snow gvanrossum commented on Nov 21, 2023 I still find it jarring to see the labels to the left of the line numbers. I'm so used to line numbers being the leftmost piece of information in any presentation where they are relevant. I think this would also make it easier to guess the difference between the two numbers (line and offset).
Finally. Is it time to switch to instruction indices, from byte offsets? This would halve the numbers, and make it easier to correlate them to things actually found in variables or other debug output (e.g. lltrace). markshannon commented on Nov 21, 2023
I think it would be nice to have -- instead of None for no line number.
None is the value you get from code.co_lines() for those instructions.
What is the advantage of --?
Is it time to switch to instruction indices, from byte offsets?
You mean code unit offsets, not instruction offsets?
Instructions are of differing lengths. They happen to all be a multiple of 2 at the moment, but they weren't in the past and might not be in the future. markshannon commented on Nov 21, 2023 Perhaps we should make the default what we have now (for backwards compatibility, not because it is the best or prettiest) and allow the user to choose the format.
For example, --format=JLIA would mean "Jump-targets Lines Instruction Arguments"
The default being LOIA (Line Offset Instruction Argument)
Or is that just getting too complicated? iritkatriel commented on Nov 22, 2023
I think it would be nice to have -- instead of None for no line number.
None is the value you get from code.co_lines() for those instructions. What is the advantage of --?
I think it would be more pleasing visually in the output. iritkatriel commented on Nov 22, 2023 New version is:
iritkatriel@Irits-MBP cpython % cat xx.py
if a:
try:
1/0
except:
pass
iritkatriel@Irits-MBP cpython % ./python.exe -m dis xx.py
0 RESUME 0
2 LOAD_NAME 0 (a)
TO_BOOL
POP_JUMP_IF_FALSE 7 (to L3)
3 NOP
4 L1: LOAD_CONST 0 (1)
LOAD_CONST 1 (0)
BINARY_OP 11 (/)
POP_TOP
L2: RETURN_CONST 2 (None)
2 L3: RETURN_CONST 2 (None)
None L4: PUSH_EXC_INFO
5 POP_TOP
6 L5: POP_EXCEPT
RETURN_CONST 2 (None)
None L6: COPY 3
POP_EXCEPT
RERAISE 1
ExceptionTable:
L1 to L2 -> L4 [0]
L4 to L5 -> L6 [1] lasti
iritkatriel@Irits-MBP cpython % ./python.exe -m dis -O xx.py
0 0 RESUME 0
2 2 LOAD_NAME 0 (a)
4 TO_BOOL
12 POP_JUMP_IF_FALSE 7 (to L3)
3 16 NOP
4 L1: 18 LOAD_CONST 0 (1)
20 LOAD_CONST 1 (0)
22 BINARY_OP 11 (/)
26 POP_TOP
L2: 28 RETURN_CONST 2 (None)
2 L3: 30 RETURN_CONST 2 (None)
None L4: 32 PUSH_EXC_INFO
5 34 POP_TOP
6 L5: 36 POP_EXCEPT
38 RETURN_CONST 2 (None)
None L6: 40 COPY 3
42 POP_EXCEPT
44 RERAISE 1
ExceptionTable:
L1 to L2 -> L4 [0]
L4 to L5 -> L6 [1] lasti
iritkatriel commented on Nov 22, 2023 With -- instead of None it looks like this:
0 RESUME 0
2 LOAD_NAME 0 (a)
TO_BOOL
POP_JUMP_IF_FALSE 7 (to L3)
3 NOP
4 L1: LOAD_CONST 0 (1)
LOAD_CONST 1 (0)
BINARY_OP 11 (/)
POP_TOP
L2: RETURN_CONST 2 (None)
2 L3: RETURN_CONST 2 (None)
-- L4: PUSH_EXC_INFO
5 POP_TOP
6 L5: POP_EXCEPT
RETURN_CONST 2 (None)
-- L6: COPY 3
POP_EXCEPT
RERAISE 1
ExceptionTable:
L1 to L2 -> L4 [0]
L4 to L5 -> L6 [1] lasti
gvanrossum commented on Nov 22, 2023 Unsurprisingly I like the version best with '--' for unknown line numbers, labels, byte (or instr!) offsets. In fact I can't wait to use it. :-)
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|