8000 bpo-44626: Merge basic blocks earlier to enable better handling of ex… · python/cpython@37686f7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 37686f7

Browse files
authored
bpo-44626: Merge basic blocks earlier to enable better handling of exit blocks without line numbers (GH-27138) (GH-27182)
(cherry picked from commit a86f7da)
1 parent 0e349ea commit 37686f7

File tree

5 files changed

+3893
-3827
lines changed

5 files changed

+3893
-3827
lines changed

Lib/test/test_dis.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ def jumpy():
10691069
Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=144, argrepr='to 144', offset=118, starts_line=None, is_jump_target=False),
10701070
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=120, starts_line=22, is_jump_target=True),
10711071
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=122, starts_line=None, is_jump_target=False),
1072-
Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=106, argval=212, argrepr='to 212', offset=124, starts_line=None, is_jump_target=False),
1072+
Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=120, argval=240, argrepr='to 240', offset=124, starts_line=None, is_jump_target=False),
10731073
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False),
10741074
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False),
10751075
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False),
@@ -1078,7 +1078,7 @@ def jumpy():
10781078
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False),
10791079
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False),
10801080
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False),
1081-
Instruction(opname='JUMP_FORWARD', opcode=110, arg=22, argval=188, argrepr='to 188', offset=142, starts_line=None, is_jump_target=False),
1081+
Instruction(opname='JUMP_FORWARD', opcode=110, arg=41, argval=226, argrepr='to 226', offset=142, starts_line=N D7AE one, is_jump_target=False),
10821082
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True),
10831083
Instruction(opname='SETUP_WITH', opcode=143, arg=12, argval=172, argrepr='to 172', offset=146, starts_line=None, is_jump_target=False),
10841084
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False),
@@ -1092,7 +1092,7 @@ def jumpy():
10921092
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False),
10931093
Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=166, starts_line=None, is_jump_target=False),
10941094
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False),
1095-
Instruction(opname='JUMP_FORWARD', opcode=110, arg=8, argval=188, argrepr='to 188', offset=170, starts_line=None, is_jump_target=False),
1095+
Instruction(opname='JUMP_FORWARD', opcode=110, arg=20, argval=212, argrepr='to 212', offset=170, starts_line=None, is_jump_target=False),
10961096
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=True),
10971097
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=89, argval=178, argrepr='to 178', offset=174, starts_line=None, is_jump_target=False),
10981098
Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=176, starts_line=None, is_jump_target=False),
@@ -1101,7 +1101,7 @@ def jumpy():
11011101
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False),
11021102
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False),
11031103
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False),
1104-
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=True),
1104+
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False),
11051105
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=190, starts_line=28, is_jump_target=False),
11061106
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=192, starts_line=None, is_jump_target=False),
11071107
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=194, starts_line=None, is_jump_target=False),
@@ -1113,7 +1113,21 @@ def jumpy():
11131113
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=206, starts_line=None, is_jump_target=False),
11141114
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False),
11151115
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=210, starts_line=None, is_jump_target=False),
1116-
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=212, starts_line=22, is_jump_target=True),
1116+
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=212, starts_line=25, is_jump_target=True),
1117+
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=214, starts_line=28, is_jump_target=False),
1118+
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=216, starts_line=None, is_jump_target=False),
1119+
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False),
1120+
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=220, starts_line=None, is_jump_target=False),
1121+
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=222, starts_line=None, is_jump_target=False),
1122+
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False),
1123+
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=226, starts_line=23, is_jump_target=True),
1124+
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=228, starts_line=28, is_jump_target=False),
1125+
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=230, starts_line=None, is_jump_target=False),
1126+
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=232, starts_line=None, is_jump_target=False),
1127+
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False),
1128+
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=236, starts_line=None, is_jump_target=False),
1129+
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False),
1130+
Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=240, starts_line=22, is_jump_target=True),
11171131
]
11181132

11191133
# One last piece of inspect fodder to check the default line number handling

Lib/test/test_sys_settrace.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -986,14 +986,29 @@ def func():
986986
except Exception:
987987
pass
988988

989-
# This doesn't conform to PEP 626
990989
self.run_and_compare(func,
991990
[(0, 'call'),
992991
(1, 'line'),
993992
(2, 'line'),
994993
(3, 'line'),
995-
(5, 'line'),
996-
(5, 'return')])
994+
(3, 'return')])
995+
996+
def test_if_in_if_in_if(self):
997+
def func(a=0, p=1, z=1):
998+
if p:
999+
if a:
1000+
if z:
1001+
pass
1002+
else:
1003+
pass
1004+
else:
1005+
pass
1006+
1007+
self.run_and_compare(func,
1008+
[(0, 'call'),
1009+
(1, 'line'),
1010+
(2, 'line'),
1011+
(2, 'return')])
9971012

9981013
def test_early_exit_with(self):
9991014

Python/compile.c

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6934,10 +6934,11 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts)
69346934
/* For debugging purposes only */
69356935
#if 0
69366936
static void
6937-
dump_instr(const struct instr *i)
6937+
dump_instr(struct instr *i)
69386938
{
6939-
const char *jrel = (is_relative_jump(instr)) ? "jrel " : "";
6940-
const char *jabs = (is_jump(instr) && !is_relative_jump(instr))? "jabs " : "";
6939+
const char *jrel = (is_relative_jump(i)) ? "jrel " : "";
6940+
const char *jabs = (is_jump(i) && !is_relative_jump(i))? "jabs " : "";
6941+
69416942
char arg[128];
69426943

69436944
*arg = '\0';
@@ -6974,6 +6975,9 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts);
69746975
static int
69756976
ensure_exits_have_lineno(struct compiler *c);
69766977

6978+
static int
6979+
extend_block(basicblock *bb);
6980+
69776981
static int
69786982
insert_generator_prefix(struct compiler *c, basicblock *entryblock) {
69796983

@@ -7063,6 +7067,12 @@ assemble(struct compiler *c, int addNone)
70637067
}
70647068
}
70657069

7070+
for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) {
7071+
if (extend_block(b)) {
7072+
return NULL;
7073+
}
7074+
}
7075+
70667076
if (ensure_exits_have_lineno(c)) {
70677077
return NULL;
70687078
}
@@ -7096,6 +7106,7 @@ assemble(struct compiler *c, int addNone)
70967106
if (consts == NULL) {
70977107
goto error;
70987108
}
7109+
70997110
if (optimize_cfg(c, &a, consts)) {
71007111
goto error;
71017112
}
@@ -7459,19 +7470,14 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
74597470
goto error;
74607471
}
74617472
break;
7462-
default:
7463-
if (inst->i_target->b_exit && inst->i_target->b_iused <= MAX_COPY_SIZE) {
7464-
basicblock *to_copy = inst->i_target;
7465-
inst->i_opcode = NOP;
7466-
for (i = 0; i < to_copy->b_iused; i++) {
7467-
int index = compiler_next_instr(bb);
7468-
if (index < 0) {
7469-
return -1;
7470-
}
7471-
bb->b_instr[index] = to_copy->b_instr[i];
7472-
}
7473-
bb->b_exit = 1;
7474-
}
7473+
}
7474+
break;
7475+
case FOR_ITER:
7476+
assert (i == bb->b_iused-1);
7477+
if (target->i_opcode == JUMP_FORWARD) {
7478+
if (eliminate_jump_to_jump(bb, inst->i_opcode)) {
7479+
goto error;
7480+
}
74757481
}
74767482
break;
74777483
case ROT_N:
@@ -7501,6 +7507,32 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
75017507
return -1;
75027508
}
75037509

7510+
/* If this block ends with an unconditional jump to an exit block,
7511+
* then remove the jump and extend this block with the target.
7512+
*/
7513+
static int
7514+
extend_block(basicblock *bb) {
7515+
if (bb->b_iused == 0) {
7516+
return 0;
7517+
}
7518+
struct instr *last = &bb->b_instr[bb->b_iused-1];
7519+
if (last->i_opcode != JUMP_ABSOLUTE && last A71E ->i_opcode != JUMP_FORWARD) {
7520+
return 0;
7521+
}
7522+
if (last->i_target->b_exit && last->i_target->b_iused <= MAX_COPY_SIZE) {
7523+
basicblock *to_copy = last->i_target;
7524+
last->i_opcode = NOP;
7525+
for (int i = 0; i < to_copy->b_iused; i++) {
7526+
int index = compiler_next_instr(bb);
7527+
if (index < 0) {
7528+
return -1;
7529+
}
7530+
bb->b_instr[index] = to_copy->b_instr[i];
7531+
}
7532+
bb->b_exit = 1;
7533+
}
7534+
return 0;
7535+
}
75047536

75057537
static void
75067538
clean_basic_block(basicblock *bb, int prev_lineno) {

0 commit comments

Comments
 (0)
0