bpo-42246: Eliminate jumps to exit blocks by copying those blocks. (#23251)
* Compiler: eliminate jumps to short exit blocks by copying.
This commit is contained in:
parent
750c5abf43
commit
cc75ab791d
|
@ -264,47 +264,47 @@ dis_compound_stmt_str = """\
|
||||||
8 INPLACE_ADD
|
8 INPLACE_ADD
|
||||||
10 STORE_NAME 0 (x)
|
10 STORE_NAME 0 (x)
|
||||||
12 JUMP_ABSOLUTE 4
|
12 JUMP_ABSOLUTE 4
|
||||||
14 LOAD_CONST 2 (None)
|
|
||||||
16 RETURN_VALUE
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dis_traceback = """\
|
dis_traceback = """\
|
||||||
%3d 0 SETUP_FINALLY 12 (to 14)
|
%3d 0 SETUP_FINALLY 14 (to 16)
|
||||||
|
|
||||||
%3d 2 LOAD_CONST 1 (1)
|
%3d 2 LOAD_CONST 1 (1)
|
||||||
4 LOAD_CONST 2 (0)
|
4 LOAD_CONST 2 (0)
|
||||||
--> 6 BINARY_TRUE_DIVIDE
|
--> 6 BINARY_TRUE_DIVIDE
|
||||||
8 POP_TOP
|
8 POP_TOP
|
||||||
10 POP_BLOCK
|
10 POP_BLOCK
|
||||||
12 JUMP_FORWARD 42 (to 56)
|
|
||||||
|
|
||||||
%3d >> 14 DUP_TOP
|
%3d 12 LOAD_FAST 1 (tb)
|
||||||
16 LOAD_GLOBAL 0 (Exception)
|
14 RETURN_VALUE
|
||||||
18 JUMP_IF_NOT_EXC_MATCH 54
|
|
||||||
20 POP_TOP
|
|
||||||
22 STORE_FAST 0 (e)
|
|
||||||
24 POP_TOP
|
|
||||||
26 SETUP_FINALLY 18 (to 46)
|
|
||||||
|
|
||||||
%3d 28 LOAD_FAST 0 (e)
|
%3d >> 16 DUP_TOP
|
||||||
30 LOAD_ATTR 1 (__traceback__)
|
18 LOAD_GLOBAL 0 (Exception)
|
||||||
32 STORE_FAST 1 (tb)
|
20 JUMP_IF_NOT_EXC_MATCH 58
|
||||||
34 POP_BLOCK
|
22 POP_TOP
|
||||||
36 POP_EXCEPT
|
24 STORE_FAST 0 (e)
|
||||||
38 LOAD_CONST 0 (None)
|
26 POP_TOP
|
||||||
40 STORE_FAST 0 (e)
|
28 SETUP_FINALLY 20 (to 50)
|
||||||
42 DELETE_FAST 0 (e)
|
|
||||||
44 JUMP_FORWARD 10 (to 56)
|
|
||||||
>> 46 LOAD_CONST 0 (None)
|
|
||||||
48 STORE_FAST 0 (e)
|
|
||||||
50 DELETE_FAST 0 (e)
|
|
||||||
52 RERAISE
|
|
||||||
>> 54 RERAISE
|
|
||||||
|
|
||||||
%3d >> 56 LOAD_FAST 1 (tb)
|
%3d 30 LOAD_FAST 0 (e)
|
||||||
58 RETURN_VALUE
|
32 LOAD_ATTR 1 (__traceback__)
|
||||||
|
34 STORE_FAST 1 (tb)
|
||||||
|
36 POP_BLOCK
|
||||||
|
38 POP_EXCEPT
|
||||||
|
40 LOAD_CONST 0 (None)
|
||||||
|
42 STORE_FAST 0 (e)
|
||||||
|
44 DELETE_FAST 0 (e)
|
||||||
|
|
||||||
|
%3d 46 LOAD_FAST 1 (tb)
|
||||||
|
48 RETURN_VALUE
|
||||||
|
>> 50 LOAD_CONST 0 (None)
|
||||||
|
52 STORE_FAST 0 (e)
|
||||||
|
54 DELETE_FAST 0 (e)
|
||||||
|
56 RERAISE
|
||||||
|
>> 58 RERAISE
|
||||||
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
||||||
TRACEBACK_CODE.co_firstlineno + 2,
|
TRACEBACK_CODE.co_firstlineno + 2,
|
||||||
|
TRACEBACK_CODE.co_firstlineno + 5,
|
||||||
TRACEBACK_CODE.co_firstlineno + 3,
|
TRACEBACK_CODE.co_firstlineno + 3,
|
||||||
TRACEBACK_CODE.co_firstlineno + 4,
|
TRACEBACK_CODE.co_firstlineno + 4,
|
||||||
TRACEBACK_CODE.co_firstlineno + 5)
|
TRACEBACK_CODE.co_firstlineno + 5)
|
||||||
|
@ -992,7 +992,7 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=2, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=2, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False),
|
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='FOR_ITER', opcode=93, arg=34, argval=44, argrepr='to 44', offset=8, starts_line=None, is_jump_target=True),
|
Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=42, argrepr='to 42', offset=8, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=10, starts_line=None, is_jump_target=False),
|
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=10, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=12, starts_line=4, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=12, starts_line=4, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=14, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=14, starts_line=None, is_jump_target=False),
|
||||||
|
@ -1008,93 +1008,90 @@ expected_opinfo_jumpy = [
|
||||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=34, starts_line=None, is_jump_target=False),
|
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=34, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=8, argval=8, argrepr='', offset=36, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=8, argval=8, argrepr='', offset=36, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=8, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=8, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=52, argrepr='', offset=40, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=50, argval=50, argrepr='', offset=40, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=8, argval=8, argrepr='', offset=42, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=42, starts_line=10, is_jump_target=True),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=44, starts_line=10, is_jump_target=True),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=44, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=46, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=46, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=48, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=48, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=50, starts_line=11, is_jump_target=True),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, starts_line=11, is_jump_target=True),
|
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=90, argval=90, argrepr='', offset=52, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=94, argval=94, argrepr='', offset=54, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=54, starts_line=12, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=56, starts_line=12, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=58, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=58, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=60, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=13, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=64, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False),
|
Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=68, starts_line=None, is_jump_target=False),
|
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=68, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=70, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=70, starts_line=14, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=72, starts_line=14, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=72, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=74, starts_line=None, is_jump_target=False),
|
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=74, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=76, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=80, argval=80, argrepr='', offset=76, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=82, argval=82, argrepr='', offset=78, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=50, argval=50, argrepr='', offset=78, starts_line=15, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=52, argrepr='', offset=80, starts_line=15, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=80, starts_line=16, is_jump_target=True),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=82, starts_line=16, is_jump_target=True),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=82, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=84, starts_line=None, is_jump_target=False),
|
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=84, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=86, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=50, argval=50, argrepr='', offset=86, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=52, argval=52, argrepr='', offset=88, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=98, argval=98, argrepr='', offset=88, starts_line=17, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=102, argval=102, argrepr='', offset=90, starts_line=17, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=90, starts_line=19, is_jump_target=True),
|
||||||
Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=52, argrepr='', offset=92, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=92, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=94, starts_line=19, is_jump_target=True),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=94, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=96, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=96, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=98, starts_line=None, is_jump_target=False),
|
Instruction(opname='SETUP_FINALLY', opcode=122, arg=98, argval=198, argrepr='to 198', offset=98, starts_line=20, is_jump_target=True),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=100, starts_line=None, is_jump_target=False),
|
Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=114, argrepr='to 114', offset=100, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='SETUP_FINALLY', opcode=122, arg=96, argval=200, argrepr='to 200', offset=102, starts_line=20, is_jump_target=True),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=102, starts_line=21, is_jump_target=False),
|
||||||
Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=104, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False),
|
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=108, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=140, argrepr='to 140', offset=112, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False),
|
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=114, starts_line=22, is_jump_target=True),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=144, argrepr='to 144', offset=116, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=116, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=118, starts_line=22, is_jump_target=True),
|
Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=138, argval=138, argrepr='', offset=118, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=120, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=120, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=142, argval=142, argrepr='', offset=122, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=122, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=126, starts_line=23, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=128, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=130, starts_line=23, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=130, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=132, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=134, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=46, argval=184, argrepr='to 184', offset=136, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False),
|
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=46, argval=188, argrepr='to 188', offset=140, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=140, starts_line=25, is_jump_target=True),
|
||||||
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=True),
|
Instruction(opname='SETUP_WITH', opcode=143, arg=24, argval=168, argrepr='to 168', offset=142, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True),
|
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=144, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='SETUP_WITH', opcode=143, arg=24, argval=172, argrepr='to 172', offset=146, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=146, starts_line=26, is_jump_target=False),
|
||||||
Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=148, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=150, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=154, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=156, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False),
|
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=160, starts_line=None, is_jump_target=False),
|
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=162, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=166, starts_line=None, is_jump_target=False),
|
Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=184, argrepr='to 184', offset=166, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False),
|
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=188, argrepr='to 188', offset=170, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=174, argval=174, argrepr='', offset=170, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=True),
|
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=178, argval=178, argrepr='', offset=174, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=True),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=186, starts_line=28, is_jump_target=False),
|
||||||
Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=True),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=188, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=190, starts_line=28, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=190, starts_line=None, is_jump_target=False),
|
||||||
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),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=194, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=194, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False),
|
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=10, argval=210, argrepr='to 210', offset=198, starts_line=None, is_jump_target=False),
|
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=198, starts_line=None, is_jump_target=True),
|
||||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=200, starts_line=None, is_jump_target=True),
|
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=200, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=202, starts_line=None, is_jump_target=False),
|
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=202, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=204, starts_line=None, is_jump_target=False),
|
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False),
|
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False),
|
||||||
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False),
|
|
||||||
Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=210, starts_line=None, is_jump_target=True),
|
|
||||||
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# One last piece of inspect fodder to check the default line number handling
|
# One last piece of inspect fodder to check the default line number handling
|
||||||
|
|
|
@ -990,7 +990,7 @@ class JumpTestCase(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
output.append(12)
|
output.append(12)
|
||||||
|
|
||||||
@jump_test(3, 4, [1], (ValueError, 'unreachable'))
|
@jump_test(3, 4, [1], (ValueError, 'after'))
|
||||||
def test_no_jump_infinite_while_loop(output):
|
def test_no_jump_infinite_while_loop(output):
|
||||||
output.append(1)
|
output.append(1)
|
||||||
while True:
|
while True:
|
||||||
|
|
131
Python/compile.c
131
Python/compile.c
|
@ -96,6 +96,10 @@ typedef struct basicblock_ {
|
||||||
/* b_return is true if a RETURN_VALUE opcode is inserted. */
|
/* b_return is true if a RETURN_VALUE opcode is inserted. */
|
||||||
unsigned b_return : 1;
|
unsigned b_return : 1;
|
||||||
unsigned b_reachable : 1;
|
unsigned b_reachable : 1;
|
||||||
|
/* Basic block has no fall through (it ends with a return, raise or jump) */
|
||||||
|
unsigned b_nofallthrough : 1;
|
||||||
|
/* Basic block exits scope (it ends with a return or raise) */
|
||||||
|
unsigned b_exit : 1;
|
||||||
/* depth of stack upon entry of block, computed by stackdepth() */
|
/* depth of stack upon entry of block, computed by stackdepth() */
|
||||||
int b_startdepth;
|
int b_startdepth;
|
||||||
/* instruction offset for block, computed by assemble_jump_offsets() */
|
/* instruction offset for block, computed by assemble_jump_offsets() */
|
||||||
|
@ -5434,28 +5438,14 @@ struct assembler {
|
||||||
PyObject *a_bytecode; /* string containing bytecode */
|
PyObject *a_bytecode; /* string containing bytecode */
|
||||||
int a_offset; /* offset into bytecode */
|
int a_offset; /* offset into bytecode */
|
||||||
int a_nblocks; /* number of reachable blocks */
|
int a_nblocks; /* number of reachable blocks */
|
||||||
basicblock **a_reverse_postorder; /* list of blocks in dfs postorder */
|
|
||||||
PyObject *a_lnotab; /* string containing lnotab */
|
PyObject *a_lnotab; /* string containing lnotab */
|
||||||
int a_lnotab_off; /* offset into lnotab */
|
int a_lnotab_off; /* offset into lnotab */
|
||||||
int a_prevlineno; /* lineno of last emitted line in line table */
|
int a_prevlineno; /* lineno of last emitted line in line table */
|
||||||
int a_lineno; /* lineno of last emitted instruction */
|
int a_lineno; /* lineno of last emitted instruction */
|
||||||
int a_lineno_start; /* bytecode start offset of current lineno */
|
int a_lineno_start; /* bytecode start offset of current lineno */
|
||||||
|
basicblock *a_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
dfs(struct compiler *c, basicblock *b, struct assembler *a, int end)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* There is no real depth-first-search to do here because all the
|
|
||||||
* blocks are emitted in topological order already, so we just need to
|
|
||||||
* follow the b_next pointers and place them in a->a_reverse_postorder in
|
|
||||||
* reverse order and make sure that the first one starts at 0. */
|
|
||||||
|
|
||||||
for (a->a_nblocks = 0; b != NULL; b = b->b_next) {
|
|
||||||
a->a_reverse_postorder[a->a_nblocks++] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_LOCAL_INLINE(void)
|
Py_LOCAL_INLINE(void)
|
||||||
stackdepth_push(basicblock ***sp, basicblock *b, int depth)
|
stackdepth_push(basicblock ***sp, basicblock *b, int depth)
|
||||||
{
|
{
|
||||||
|
@ -5553,12 +5543,7 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
a->a_reverse_postorder = (basicblock **)PyObject_Malloc(
|
|
||||||
sizeof(basicblock *) * nblocks);
|
|
||||||
if (!a->a_reverse_postorder) {
|
|
||||||
PyErr_NoMemory();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5567,8 +5552,6 @@ assemble_free(struct assembler *a)
|
||||||
{
|
{
|
||||||
Py_XDECREF(a->a_bytecode);
|
Py_XDECREF(a->a_bytecode);
|
||||||
Py_XDECREF(a->a_lnotab);
|
Py_XDECREF(a->a_lnotab);
|
||||||
if (a->a_reverse_postorder)
|
|
||||||
PyObject_Free(a->a_reverse_postorder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -5697,8 +5680,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
||||||
Replace block pointer with position in bytecode. */
|
Replace block pointer with position in bytecode. */
|
||||||
do {
|
do {
|
||||||
totsize = 0;
|
totsize = 0;
|
||||||
for (i = 0; i < a->a_nblocks; i++) {
|
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
|
||||||
b = a->a_reverse_postorder[i];
|
|
||||||
bsize = blocksize(b);
|
bsize = blocksize(b);
|
||||||
b->b_offset = totsize;
|
b->b_offset = totsize;
|
||||||
totsize += bsize;
|
totsize += bsize;
|
||||||
|
@ -5966,7 +5948,7 @@ assemble(struct compiler *c, int addNone)
|
||||||
{
|
{
|
||||||
basicblock *b, *entryblock;
|
basicblock *b, *entryblock;
|
||||||
struct assembler a;
|
struct assembler a;
|
||||||
int i, j, nblocks;
|
int j, nblocks;
|
||||||
PyCodeObject *co = NULL;
|
PyCodeObject *co = NULL;
|
||||||
PyObject *consts = NULL;
|
PyObject *consts = NULL;
|
||||||
|
|
||||||
|
@ -5997,7 +5979,8 @@ assemble(struct compiler *c, int addNone)
|
||||||
}
|
}
|
||||||
if (!assemble_init(&a, nblocks, c->u->u_firstlineno))
|
if (!assemble_init(&a, nblocks, c->u->u_firstlineno))
|
||||||
goto error;
|
goto error;
|
||||||
dfs(c, entryblock, &a, nblocks);
|
a.a_entry = entryblock;
|
||||||
|
a.a_nblocks = nblocks;
|
||||||
|
|
||||||
consts = consts_dict_keys_inorder(c->u->u_consts);
|
consts = consts_dict_keys_inorder(c->u->u_consts);
|
||||||
if (consts == NULL) {
|
if (consts == NULL) {
|
||||||
|
@ -6010,9 +5993,8 @@ assemble(struct compiler *c, int addNone)
|
||||||
/* Can't modify the bytecode after computing jump offsets. */
|
/* Can't modify the bytecode after computing jump offsets. */
|
||||||
assemble_jump_offsets(&a, c);
|
assemble_jump_offsets(&a, c);
|
||||||
|
|
||||||
/* Emit code in reverse postorder from dfs. */
|
/* Emit code. */
|
||||||
for (i = 0; i < a.a_nblocks; i++) {
|
for(b = entryblock; b != NULL; b = b->b_next) {
|
||||||
b = a.a_reverse_postorder[i];
|
|
||||||
for (j = 0; j < b->b_iused; j++)
|
for (j = 0; j < b->b_iused; j++)
|
||||||
if (!assemble_emit(&a, &b->b_instr[j]))
|
if (!assemble_emit(&a, &b->b_instr[j]))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -6097,6 +6079,8 @@ fold_tuple_on_constants(struct instr *inst,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Maximum size of basic block that should be copied in optimizer */
|
||||||
|
#define MAX_COPY_SIZE 4
|
||||||
|
|
||||||
/* Optimization */
|
/* Optimization */
|
||||||
static int
|
static int
|
||||||
|
@ -6238,19 +6222,29 @@ optimize_basic_block(basicblock *bb, PyObject *consts)
|
||||||
|
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
|
assert (i == bb->b_iused-1);
|
||||||
switch(target->i_opcode) {
|
switch(target->i_opcode) {
|
||||||
case JUMP_FORWARD:
|
case JUMP_FORWARD:
|
||||||
inst->i_target = target->i_target;
|
inst->i_target = target->i_target;
|
||||||
break;
|
break;
|
||||||
case JUMP_ABSOLUTE:
|
case JUMP_ABSOLUTE:
|
||||||
case RETURN_VALUE:
|
|
||||||
case RERAISE:
|
|
||||||
case RAISE_VARARGS:
|
|
||||||
lineno = inst->i_lineno;
|
lineno = inst->i_lineno;
|
||||||
*inst = *target;
|
*inst = *target;
|
||||||
inst->i_lineno = lineno;
|
inst->i_lineno = lineno;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (inst->i_target->b_exit && inst->i_target->b_iused <= MAX_COPY_SIZE) {
|
||||||
|
basicblock *to_copy = inst->i_target;
|
||||||
|
*inst = to_copy->b_instr[0];
|
||||||
|
for (i = 1; i < to_copy->b_iused; i++) {
|
||||||
|
int index = compiler_next_instr(bb);
|
||||||
|
if (index < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bb->b_instr[index] = to_copy->b_instr[i];
|
||||||
|
}
|
||||||
|
bb->b_exit = 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6262,52 +6256,63 @@ error:
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clean_basic_block(basicblock *bb) {
|
clean_basic_block(basicblock *bb) {
|
||||||
/* Remove NOPs and any code following a return or re-raise. */
|
/* Remove NOPs. */
|
||||||
int dest = 0;
|
int dest = 0;
|
||||||
int prev_lineno = -1;
|
int prev_lineno = -1;
|
||||||
for (int src = 0; src < bb->b_iused; src++) {
|
for (int src = 0; src < bb->b_iused; src++) {
|
||||||
int lineno = bb->b_instr[src].i_lineno;
|
int lineno = bb->b_instr[src].i_lineno;
|
||||||
switch(bb->b_instr[src].i_opcode) {
|
if (bb->b_instr[src].i_opcode == NOP) {
|
||||||
case RETURN_VALUE:
|
|
||||||
case RERAISE:
|
|
||||||
bb->b_next = NULL;
|
|
||||||
bb->b_instr[dest] = bb->b_instr[src];
|
|
||||||
dest++;
|
|
||||||
goto end;
|
|
||||||
case NOP:
|
|
||||||
{
|
|
||||||
/* Eliminate no-op if it doesn't have a line number, or
|
/* Eliminate no-op if it doesn't have a line number, or
|
||||||
* if the next instruction has same line number or no line number, or
|
* if the next instruction has same line number or no line number, or
|
||||||
* if the previous instruction had the same line number. */
|
* if the previous instruction had the same line number. */
|
||||||
if (lineno < 0) {
|
if (lineno < 0) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
if (prev_lineno == lineno) {
|
if (prev_lineno == lineno) {
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
if (src < bb->b_iused - 1) {
|
if (src < bb->b_iused - 1) {
|
||||||
int next_lineno = bb->b_instr[src+1].i_lineno;
|
int next_lineno = bb->b_instr[src+1].i_lineno;
|
||||||
if (next_lineno < 0 || next_lineno == lineno) {
|
if (next_lineno < 0 || next_lineno == lineno) {
|
||||||
bb->b_instr[src+1].i_lineno = lineno;
|
bb->b_instr[src+1].i_lineno = lineno;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* fallthrough */
|
|
||||||
default:
|
|
||||||
if (dest != src) {
|
if (dest != src) {
|
||||||
bb->b_instr[dest] = bb->b_instr[src];
|
bb->b_instr[dest] = bb->b_instr[src];
|
||||||
}
|
}
|
||||||
dest++;
|
dest++;
|
||||||
prev_lineno = lineno;
|
prev_lineno = lineno;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
end:
|
|
||||||
assert(dest <= bb->b_iused);
|
assert(dest <= bb->b_iused);
|
||||||
bb->b_iused = dest;
|
bb->b_iused = dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
normalise_basic_block(basicblock *bb) {
|
||||||
|
/* Remove any code following a return or re-raise,
|
||||||
|
and mark those blocks as exit and/or nofallthrough. */
|
||||||
|
for (int i = 0; i < bb->b_iused; i++) {
|
||||||
|
switch(bb->b_instr[i].i_opcode) {
|
||||||
|
case RETURN_VALUE:
|
||||||
|
case RAISE_VARARGS:
|
||||||
|
case RERAISE:
|
||||||
|
bb->b_iused = i+1;
|
||||||
|
bb->b_exit = 1;
|
||||||
|
bb->b_nofallthrough = 1;
|
||||||
|
return;
|
||||||
|
case JUMP_ABSOLUTE:
|
||||||
|
case JUMP_FORWARD:
|
||||||
|
bb->b_iused = i+1;
|
||||||
|
bb->b_nofallthrough = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mark_reachable(struct assembler *a) {
|
mark_reachable(struct assembler *a) {
|
||||||
basicblock **stack, **sp;
|
basicblock **stack, **sp;
|
||||||
|
@ -6315,12 +6320,11 @@ mark_reachable(struct assembler *a) {
|
||||||
if (stack == NULL) {
|
if (stack == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
basicblock *entry = a->a_reverse_postorder[0];
|
a->a_entry->b_reachable = 1;
|
||||||
entry->b_reachable = 1;
|
*sp++ = a->a_entry;
|
||||||
*sp++ = entry;
|
|
||||||
while (sp > stack) {
|
while (sp > stack) {
|
||||||
basicblock *b = *(--sp);
|
basicblock *b = *(--sp);
|
||||||
if (b->b_next && b->b_next->b_reachable == 0) {
|
if (b->b_next && !b->b_nofallthrough && b->b_next->b_reachable == 0) {
|
||||||
b->b_next->b_reachable = 1;
|
b->b_next->b_reachable = 1;
|
||||||
*sp++ = b->b_next;
|
*sp++ = b->b_next;
|
||||||
}
|
}
|
||||||
|
@ -6352,20 +6356,23 @@ mark_reachable(struct assembler *a) {
|
||||||
static int
|
static int
|
||||||
optimize_cfg(struct assembler *a, PyObject *consts)
|
optimize_cfg(struct assembler *a, PyObject *consts)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < a->a_nblocks; i++) {
|
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
|
||||||
if (optimize_basic_block(a->a_reverse_postorder[i], consts)) {
|
normalise_basic_block(b);
|
||||||
|
}
|
||||||
|
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
|
||||||
|
if (optimize_basic_block(b, consts)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
clean_basic_block(a->a_reverse_postorder[i]);
|
clean_basic_block(b);
|
||||||
assert(a->a_reverse_postorder[i]->b_reachable == 0);
|
assert(b->b_reachable == 0);
|
||||||
}
|
}
|
||||||
if (mark_reachable(a)) {
|
if (mark_reachable(a)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Delete unreachable instructions */
|
/* Delete unreachable instructions */
|
||||||
for (int i = 0; i < a->a_nblocks; i++) {
|
for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) {
|
||||||
if (a->a_reverse_postorder[i]->b_reachable == 0) {
|
if (b->b_reachable == 0) {
|
||||||
a->a_reverse_postorder[i]->b_iused = 0;
|
b->b_iused = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue