-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
bpo-46344: Fix trace bug in else of try and try-star blocks #30544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -644,16 +644,22 @@ def func(): | |||
4 | |||
else: | |||
6 | |||
if False: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this cover the original issue?
The compiler will optimize out the if False
.
Might be a good idea to add another test with a non-constant predicate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test did fail without the fix. But sure, I'll add a test with a non const.
77a1602
to
46cf04a
Compare
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None), | ||
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None), | ||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None), | ||
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=252, starts_line=None, is_jump_target=False, positions=None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 9 more opcodes generated now. Looks like that jump enabled some optimisation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gvanrossum this PR fixes a regression from the except* PR and it’s all very odd, both the bug and the impact of the fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracing is Mark's black magic these days (I don't claim to understand the line number table code).
Could it be that test_dis.py wasn't properly regenerated in a while? It's always struck me as odd that there isn't a more direct way to cause this data to be regenerated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests fail if you don’t update it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I extracted it out of the test. I think with this PR it emits the finally body 4 times, and without it 3 times?
def jumpy():
try:
1 / 0
except ZeroDivisionError:
print("Here we go, here we go, here we go...")
else:
with i as dodgy:
print("Never reach this")
finally:
print("OK, now we're done")
import dis
dis.dis(jumpy)
Old:
1 0 RESUME 0
2 2 NOP
3 4 LOAD_CONST 1 (1)
6 LOAD_CONST 2 (0)
8 BINARY_OP 11 (/)
10 POP_TOP
12 JUMP_FORWARD 14 (to 42)
>> 14 PUSH_EXC_INFO
4 16 LOAD_GLOBAL 0 (ZeroDivisionError)
18 JUMP_IF_NOT_EXC_MATCH 17 (to 34)
20 POP_TOP
5 22 LOAD_GLOBAL 1 (print)
24 LOAD_CONST 3 ('Here we go, here we go, here we go...')
26 CALL_NO_KW 1
28 POP_TOP
30 POP_EXCEPT
32 JUMP_FORWARD 34 (to 102)
4 >> 34 RERAISE 0
>> 36 COPY 3
38 POP_EXCEPT
40 RERAISE 1
7 >> 42 LOAD_GLOBAL 2 (i)
44 BEFORE_WITH
46 STORE_FAST 0 (dodgy)
8 48 LOAD_GLOBAL 1 (print)
50 LOAD_CONST 4 ('Never reach this')
52 CALL_NO_KW 1
54 POP_TOP
7 56 LOAD_CONST 0 (None)
58 DUP_TOP
60 DUP_TOP
62 CALL_NO_KW 3
64 POP_TOP
66 JUMP_FORWARD 11 (to 90)
>> 68 PUSH_EXC_INFO
70 WITH_EXCEPT_START
72 POP_JUMP_IF_TRUE 41 (to 82)
74 RERAISE 2
>> 76 COPY 3
78 POP_EXCEPT
80 RERAISE 1
>> 82 POP_TOP
84 POP_EXCEPT
86 POP_TOP
88 POP_TOP
10 >> 90 LOAD_GLOBAL 1 (print)
92 LOAD_CONST 5 ("OK, now we're done")
94 CALL_NO_KW 1
96 POP_TOP
98 LOAD_CONST 0 (None)
100 RETURN_VALUE
5 >> 102 NOP
10 104 LOAD_GLOBAL 1 (print)
106 LOAD_CONST 5 ("OK, now we're done")
108 CALL_NO_KW 1
110 POP_TOP
112 LOAD_CONST 0 (None)
114 RETURN_VALUE
>> 116 PUSH_EXC_INFO
118 LOAD_GLOBAL 1 (print)
120 LOAD_CONST 5 ("OK, now we're done")
122 CALL_NO_KW 1
124 POP_TOP
126 RERAISE 0
>> 128 COPY 3
130 POP_EXCEPT
132 RERAISE 1
ExceptionTable:
4 to 10 -> 14 [0]
12 to 12 -> 116 [0]
14 to 28 -> 36 [1] lasti
30 to 32 -> 116 [0]
34 to 34 -> 36 [1] lasti
36 to 44 -> 116 [0]
46 to 54 -> 68 [1] lasti
56 to 66 -> 116 [0]
68 to 74 -> 76 [3] lasti
76 to 80 -> 116 [0]
82 to 82 -> 76 [3] lasti
84 to 88 -> 116 [0]
116 to 126 -> 128 [1] lasti
New:
1 0 RESUME 0
2 2 NOP
3 4 LOAD_CONST 1 (1)
6 LOAD_CONST 2 (0)
8 BINARY_OP 11 (/)
10 POP_TOP
12 JUMP_FORWARD 14 (to 42)
>> 14 PUSH_EXC_INFO
4 16 LOAD_GLOBAL 0 (ZeroDivisionError)
18 JUMP_IF_NOT_EXC_MATCH 17 (to 34)
20 POP_TOP
5 22 LOAD_GLOBAL 1 (print)
24 LOAD_CONST 3 ('Here we go, here we go, here we go...')
26 CALL_NO_KW 1
28 POP_TOP
30 POP_EXCEPT
32 JUMP_FORWARD 35 (to 104)
4 >> 34 RERAISE 0
>> 36 COPY 3
38 POP_EXCEPT
40 RERAISE 1
7 >> 42 LOAD_GLOBAL 2 (i)
44 BEFORE_WITH
46 STORE_FAST 0 (dodgy)
8 48 LOAD_GLOBAL 1 (print)
50 LOAD_CONST 4 ('Never reach this')
52 CALL_NO_KW 1
54 POP_TOP
7 56 LOAD_CONST 0 (None)
58 DUP_TOP
60 DUP_TOP
62 CALL_NO_KW 3
64 POP_TOP
66 JUMP_FORWARD 25 (to 118)
>> 68 PUSH_EXC_INFO
70 WITH_EXCEPT_START
72 POP_JUMP_IF_TRUE 41 (to 82)
74 RERAISE 2
>> 76 COPY 3
78 POP_EXCEPT
80 RERAISE 1
>> 82 POP_TOP
84 POP_EXCEPT
86 POP_TOP
88 POP_TOP
90 NOP
10 92 LOAD_GLOBAL 1 (print)
94 LOAD_CONST 5 ("OK, now we're done")
96 CALL_NO_KW 1
98 POP_TOP
100 LOAD_CONST 0 (None)
102 RETURN_VALUE
5 >> 104 NOP
10 106 LOAD_GLOBAL 1 (print)
108 LOAD_CONST 5 ("OK, now we're done")
110 CALL_NO_KW 1
112 POP_TOP
114 LOAD_CONST 0 (None)
116 RETURN_VALUE
7 >> 118 NOP
10 120 LOAD_GLOBAL 1 (print)
122 LOAD_CONST 5 ("OK, now we're done")
124 CALL_NO_KW 1
126 POP_TOP
128 LOAD_CONST 0 (None)
130 RETURN_VALUE
>> 132 PUSH_EXC_INFO
134 LOAD_GLOBAL 1 (print)
136 LOAD_CONST 5 ("OK, now we're done")
138 CALL_NO_KW 1
140 POP_TOP
142 RERAISE 0
>> 144 COPY 3
146 POP_EXCEPT
148 RERAISE 1
ExceptionTable:
4 to 10 -> 14 [0]
12 to 12 -> 132 [0]
14 to 28 -> 36 [1] lasti
30 to 32 -> 132 [0]
34 to 34 -> 36 [1] lasti
36 to 44 -> 132 [0]
46 to 54 -> 68 [1] lasti
56 to 66 -> 132 [0]
68 to 74 -> 76 [3] lasti
76 to 80 -> 132 [0]
82 to 82 -> 76 [3] lasti
84 to 88 -> 132 [0]
132 to 142 -> 144 [1] lasti
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We sometimes duplicate exit blocks to save a jump, but only if they have 4 or fewer instructions.
Maybe the explicit jump prevents that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to assume that this is what happened (this jump prevented an inlining optimization), and remove it as in the first version of this PR. This will being us back to where we were before the except* PR was merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should probably merge this before the release so that we don’t get a change in behaviour between 3.11a3 and 311.a4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree.
This PR merely highlights the excessive duplication of finally blocks. It doesn't cause it.
Do we have an issue to investigate the cause of finally block duplication?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do now: link
The fix looks good. Just needs that extra test. |
I added yesterday an additional non-const condition to the same test. Is that what you mean? |
I removed the else from the non-const if statement, so it exactly matches the case in the bpo. I've confirmed again that the test fails on current main branch. |
👍 |
|
https://bugs.python.org/issue46344