diff --git a/Include/opcode.h b/Include/opcode.h index b265368..3081463 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -44,7 +44,6 @@ extern "C" { #define BINARY_XOR 65 #define BINARY_OR 66 #define INPLACE_POWER 67 -#define GET_ITER 68 #define GET_YIELD_FROM_ITER 69 #define PRINT_EXPR 70 #define LOAD_BUILD_CLASS 71 @@ -74,6 +73,7 @@ extern "C" { #define DELETE_ATTR 96 #define STORE_GLOBAL 97 #define DELETE_GLOBAL 98 +#define FOR_BEGIN 99 #define LOAD_CONST 100 #define LOAD_NAME 101 #define BUILD_TUPLE 102 diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 034b783..d4731a7 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -226,6 +226,7 @@ _code_type = type(_write_atomic.__code__) # Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483 # Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed) # Python 3.6a0 3370 (16 bit wordcode) +# Python 3.6a2 3374 (Revise GET_ITER/FOR_ITER into FOR_BEGIN/FOR_ITER) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -234,7 +235,7 @@ _code_type = type(_write_atomic.__code__) # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3370).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3374).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index ecc24bb..8504560 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -100,7 +100,6 @@ def_op('BINARY_AND', 64) def_op('BINARY_XOR', 65) def_op('BINARY_OR', 66) def_op('INPLACE_POWER', 67) -def_op('GET_ITER', 68) def_op('GET_YIELD_FROM_ITER', 69) def_op('PRINT_EXPR', 70) @@ -130,12 +129,13 @@ HAVE_ARGUMENT = 90 # Opcodes from here have an argument: name_op('STORE_NAME', 90) # Index in name list name_op('DELETE_NAME', 91) # "" def_op('UNPACK_SEQUENCE', 92) # Number of tuple items -jrel_op('FOR_ITER', 93) +jabs_op('FOR_ITER', 93) def_op('UNPACK_EX', 94) name_op('STORE_ATTR', 95) # Index in name list name_op('DELETE_ATTR', 96) # "" name_op('STORE_GLOBAL', 97) # "" name_op('DELETE_GLOBAL', 98) # "" +jrel_op('FOR_BEGIN', 99) def_op('LOAD_CONST', 100) # Index in const list hasconst.append(100) name_op('LOAD_NAME', 101) # Index in name list diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 7e125ef..1a131c8 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -121,20 +121,19 @@ def bug708901(): pass dis_bug708901 = """\ -%3d 0 SETUP_LOOP 18 (to 20) +%3d 0 SETUP_LOOP 16 (to 18) 2 LOAD_GLOBAL 0 (range) 4 LOAD_CONST 1 (1) %3d 6 LOAD_CONST 2 (10) 8 CALL_FUNCTION 2 (2 positional, 0 keyword pair) - 10 GET_ITER - >> 12 FOR_ITER 4 (to 18) - 14 STORE_FAST 0 (res) - -%3d 16 JUMP_ABSOLUTE 12 - >> 18 POP_BLOCK - >> 20 LOAD_CONST 0 (None) - 22 RETURN_VALUE + 10 FOR_BEGIN 4 (to 16) + >> 12 STORE_FAST 0 (res) + +%3d 14 FOR_ITER 12 + >> 16 POP_BLOCK + >> 18 LOAD_CONST 0 (None) + 20 RETURN_VALUE """ % (bug708901.__code__.co_firstlineno + 1, bug708901.__code__.co_firstlineno + 2, bug708901.__code__.co_firstlineno + 3) @@ -147,22 +146,21 @@ def bug1333982(x=[]): dis_bug1333982 = """\ %3d 0 LOAD_CONST 1 (0) - 2 POP_JUMP_IF_TRUE 26 + 2 POP_JUMP_IF_TRUE 24 4 LOAD_GLOBAL 0 (AssertionError) 6 LOAD_CONST 2 ( at 0x..., file "%s", line %d>) 8 LOAD_CONST 3 ('bug1333982..') 10 MAKE_FUNCTION 0 12 LOAD_FAST 0 (x) - 14 GET_ITER - 16 CALL_FUNCTION 1 (1 positional, 0 keyword pair) + 14 CALL_FUNCTION 1 (1 positional, 0 keyword pair) -%3d 18 LOAD_CONST 4 (1) - 20 BINARY_ADD - 22 CALL_FUNCTION 1 (1 positional, 0 keyword pair) - 24 RAISE_VARARGS 1 +%3d 16 LOAD_CONST 4 (1) + 18 BINARY_ADD + 20 CALL_FUNCTION 1 (1 positional, 0 keyword pair) + 22 RAISE_VARARGS 1 -%3d >> 26 LOAD_CONST 0 (None) - 28 RETURN_VALUE +%3d >> 24 LOAD_CONST 0 (None) + 26 RETURN_VALUE """ % (bug1333982.__code__.co_firstlineno + 1, __file__, bug1333982.__code__.co_firstlineno + 1, @@ -710,103 +708,102 @@ expected_opinfo_inner = [ ] expected_opinfo_jumpy = [ - Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=54, argrepr='to 54', offset=0, starts_line=3, is_jump_target=False), + Instruction(opname='SETUP_LOOP', opcode=120, arg=50, argval=52, argrepr='to 52', offset=0, starts_line=3, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=6, starts_line=None, is_jump_target=False), - Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False), - Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=44, argrepr='to 44', offset=10, starts_line=None, is_jump_target=True), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=18, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=26, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=32, argval=32, argrepr='', offset=28, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=30, starts_line=6, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=32, starts_line=7, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=34, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=36, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=10, argval=10, argrepr='', offset=38, starts_line=None, is_jump_target=False), - Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=40, starts_line=8, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=42, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, 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=48, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=50, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False), - Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=108, argrepr='to 108', offset=54, starts_line=11, is_jump_target=True), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=True), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=98, argval=98, argrepr='', offset=58, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=60, starts_line=12, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=64, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=13, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=70, starts_line=None, is_jump_target=False), - Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=72, starts_line=None, is_jump_target=False), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=74, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=76, starts_line=14, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=78, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=80, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=86, argval=86, argrepr='', offset=82, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=84, starts_line=15, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=86, starts_line=16, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=88, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=90, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=56, argval=56, argrepr='', offset=92, starts_line=None, is_jump_target=False), - Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=94, starts_line=17, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=96, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=98, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=100, starts_line=19, 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=102, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=104, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False), - Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=180, argrepr='to 180', offset=108, starts_line=20, is_jump_target=True), - Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=124, argrepr='to 124', offset=110, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=112, starts_line=21, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=114, starts_line=None, is_jump_target=False), - Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=118, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=120, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=152, argrepr='to 152', offset=122, starts_line=None, is_jump_target=False), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=124, starts_line=22, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=126, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=128, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=150, argval=150, argrepr='', offset=130, starts_line=None, is_jump_target=False), + Instruction(opname='FOR_BEGIN', opcode=99, arg=32, argval=42, argrepr='to 42', offset=8, 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=True), + 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='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=16, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=20, starts_line=5, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=22, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=24, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=30, argval=30, argrepr='', offset=26, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=40, argval=40, argrepr='', offset=28, starts_line=6, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=30, starts_line=7, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=32, 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=40, argval=40, argrepr='', offset=36, starts_line=None, is_jump_target=False), + Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=38, starts_line=8, is_jump_target=False), + Instruction(opname='FOR_ITER', opcode=93, arg=10, argval=10, argrepr='', offset=40, starts_line=None, is_jump_target=True), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=44, starts_line=10, 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='1 positional, 0 keyword pair', 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='SETUP_LOOP', opcode=120, arg=52, argval=106, argrepr='to 106', offset=52, starts_line=11, is_jump_target=True), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=54, starts_line=None, is_jump_target=True), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=96, argval=96, argrepr='', offset=56, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=58, starts_line=12, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=60, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=62, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=13, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=68, starts_line=None, is_jump_target=False), + Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=70, starts_line=None, is_jump_target=False), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=72, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=14, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=76, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=78, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=84, argval=84, argrepr='', offset=80, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=54, argval=54, argrepr='', offset=82, starts_line=15, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=84, starts_line=16, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=86, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=88, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=54, argval=54, argrepr='', offset=90, starts_line=None, is_jump_target=False), + Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=92, starts_line=17, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=54, argval=54, argrepr='', offset=94, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=96, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=98, starts_line=19, 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=100, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=102, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=104, starts_line=None, is_jump_target=False), + Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=178, argrepr='to 178', offset=106, starts_line=20, is_jump_target=True), + Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=122, argrepr='to 122', offset=108, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=110, starts_line=21, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=112, starts_line=None, is_jump_target=False), + Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=118, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=150, argrepr='to 150', offset=120, starts_line=None, is_jump_target=False), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=122, starts_line=22, is_jump_target=True), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=124, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=126, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=148, argval=148, argrepr='', offset=128, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, 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='POP_TOP', opcode=1, 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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=138, starts_line=23, 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=140, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=142, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=176, argrepr='to 176', offset=148, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=150, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, starts_line=25, is_jump_target=True), - Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=170, argrepr='to 170', offset=154, starts_line=None, is_jump_target=False), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=156, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=26, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=160, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=162, 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='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=168, starts_line=None, is_jump_target=False), - Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True), - Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=178, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=180, starts_line=28, 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=182, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=184, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=190, starts_line=None, is_jump_target=False), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=136, starts_line=23, 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=138, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=140, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=174, argrepr='to 174', offset=146, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=148, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=150, starts_line=25, is_jump_target=True), + Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=168, argrepr='to 168', offset=152, starts_line=None, is_jump_target=False), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=154, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=156, starts_line=26, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=158, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=160, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=166, starts_line=None, is_jump_target=False), + Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=True), + Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=176, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=178, starts_line=28, 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=180, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='1 positional, 0 keyword pair', offset=182, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=188, starts_line=None, is_jump_target=False), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Makefile.pre.in b/Makefile.pre.in index 4071a2a..e729ffb 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -879,7 +879,9 @@ Objects/setobject.o: $(srcdir)/Objects/stringlib/eq.h $(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES) $(OPCODETARGETGEN) $(OPCODETARGETS_H) -Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h +Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h $(srcdir)/Python/wordcode_helpers.h +Python/compile.o: $(srcdir)/Python/wordcode_helpers.h +Python/peephole.o: $(srcdir)/Python/wordcode_helpers.h Python/frozen.o: Python/importlib.h Python/importlib_external.h diff --git a/Python/ceval.c b/Python/ceval.c index 5f8dbcd..3096ad9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -17,6 +17,7 @@ #include "opcode.h" #include "setobject.h" #include "structmember.h" +#include "wordcode_helpers.h" #include @@ -136,7 +137,8 @@ static int call_trace_protected(Py_tracefunc, PyObject *, static void call_exc_trace(Py_tracefunc, PyObject *, PyThreadState *, PyFrameObject *); static int maybe_call_line_trace(Py_tracefunc, PyObject *, - PyThreadState *, PyFrameObject *, int *, int *, int *); + PyThreadState *, PyFrameObject *, + int *, int *, int *, int, int); static PyObject * cmp_outcome(int, PyObject *, PyObject *); static PyObject * import_from(PyObject *, PyObject *); @@ -1182,9 +1184,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) When the PREDICT() macros are enabled, some opcode pairs follow in direct succession without updating f->f_lasti. A successful prediction effectively links the two codes together as if they - were a single new opcode; accordingly,f->f_lasti will point to - the first code in the pair (for instance, GET_ITER followed by - FOR_ITER is effectively a single opcode and f->f_lasti will point + were a single new opcode; accordingly, f->f_lasti will point to + the first code in the pair (for instance, FOR_ITER followed by + STORE_FAST is effectively a single opcode and f->f_lasti will point to the beginning of the combined pair.) */ next_instr = first_instr; @@ -1307,14 +1309,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (_Py_TracingPossible && tstate->c_tracefunc != NULL && !tstate->tracing) { int err; + int lasti; + if (OPCODE(*next_instr) == FOR_ITER) { + /* Trace FOR_ITER as if we're the corresponding FOR_BEGIN, + as tracer expects loop logic to precede loop body */ + lasti = (int)get_arg((unsigned char*)next_instr, 0) - 2; + } + else { + lasti = f->f_lasti; + } /* see maybe_call_line_trace for expository comments */ f->f_stacktop = stack_pointer; err = maybe_call_line_trace(tstate->c_tracefunc, - tstate->c_traceobj, - tstate, f, - &instr_lb, &instr_ub, &instr_prev); + tstate->c_traceobj, tstate, f, + &instr_lb, &instr_ub, &instr_prev, + f->f_lasti, lasti); + /* Reload possibly changed frame fields */ JUMPTO(f->f_lasti); if (f->f_stacktop != NULL) { @@ -1670,7 +1682,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(FOR_ITER); DISPATCH(); } @@ -1682,7 +1694,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(v); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(FOR_ITER); DISPATCH(); } @@ -2704,7 +2716,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(key); if (err != 0) goto error; - PREDICT(JUMP_ABSOLUTE); + PREDICT(FOR_ITER); DISPATCH(); } @@ -2920,7 +2932,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - PREDICTED(JUMP_ABSOLUTE); TARGET(JUMP_ABSOLUTE) { JUMPTO(oparg); #if FAST_LOOPS @@ -2937,18 +2948,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #endif } - TARGET(GET_ITER) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) - goto error; - PREDICT(FOR_ITER); - DISPATCH(); - } - TARGET(GET_YIELD_FROM_ITER) { /* before: [obj]; after [getiter(obj)] */ PyObject *iterable = TOP(); @@ -2977,13 +2976,48 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } - PREDICTED(FOR_ITER); + TARGET(FOR_BEGIN) { + /* before: [obj]; after: [iter, iter()] *or* [] */ + PyObject *iterable = TOP(); + PyObject *iter = PyObject_GetIter(iterable); + PyObject *next; + Py_DECREF(iterable); + SET_TOP(iter); + if (iter == NULL) + goto error; + + next = (*iter->ob_type->tp_iternext)(iter); + if (next != NULL) { + PUSH(next); + PREDICT(STORE_FAST); + PREDICT(UNPACK_SEQUENCE); + DISPATCH(); + } + if (PyErr_Occurred()) { + if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + goto error; + } + else if (tstate->c_tracefunc != NULL) { + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, + tstate, f); + } + PyErr_Clear(); + } + /* iterable is empty */ + STACKADJ(-1); + Py_DECREF(iter); + JUMPBY(oparg); + DISPATCH(); + } + + PREDICTED(FOR_ITER) TARGET(FOR_ITER) { /* before: [iter]; after: [iter, iter()] *or* [] */ PyObject *iter = TOP(); PyObject *next = (*iter->ob_type->tp_iternext)(iter); if (next != NULL) { PUSH(next); + JUMPTO(oparg); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); DISPATCH(); @@ -2992,13 +3026,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (!PyErr_ExceptionMatches(PyExc_StopIteration)) goto error; else if (tstate->c_tracefunc != NULL) - call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f); + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, + tstate, f); PyErr_Clear(); } /* iterator ended normally */ STACKADJ(-1); Py_DECREF(iter); - JUMPBY(oparg); DISPATCH(); } @@ -4423,7 +4457,7 @@ _PyEval_CallTracing(PyObject *func, PyObject *args) static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, PyThreadState *tstate, PyFrameObject *frame, - int *instr_lb, int *instr_ub, int *instr_prev) + int *instr_lb, int *instr_ub, int *instr_prev, int lasti, int nlasti) { int result = 0; int line = frame->f_lineno; @@ -4431,9 +4465,10 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, /* If the last instruction executed isn't in the current instruction window, reset the window. */ - if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) { +redo: + if (lasti < *instr_lb || lasti >= *instr_ub) { PyAddrPair bounds; - line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, + line = _PyCode_CheckLineNumber(frame->f_code, lasti, &bounds); *instr_lb = bounds.ap_lower; *instr_ub = bounds.ap_upper; @@ -4441,11 +4476,22 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, /* If the last instruction falls at the start of a line or if it represents a jump backwards, update the frame's line number and call the trace function. */ - if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) { + if (lasti == *instr_lb || lasti < *instr_prev) { frame->f_lineno = line; result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None); } - *instr_prev = frame->f_lasti; + + if (!result && lasti != nlasti) { + /* FOR_ITER may generate 2 line traces if the body is 'pass' + We want to generate a trace as if the end of the loop is a mere + JUMP_ABSOLUTE so we manually trace FOR_ITER as if FOR_BEGIN is + being executed each loop in lieu of there being no better instruction + at the beginning to designate loop iteration logic */ + lasti = nlasti; + goto redo; + } + + *instr_prev = lasti; return result; } diff --git a/Python/compile.c b/Python/compile.c index ffde903..f813925 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -908,8 +908,6 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return -1; case INPLACE_POWER: return -1; - case GET_ITER: - return 0; case PRINT_EXPR: return -1; @@ -952,6 +950,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return oparg-1; case UNPACK_EX: return (oparg&0xFF) + (oparg>>8); + + case FOR_BEGIN: case FOR_ITER: return 1; /* or -1, at end of iterator */ @@ -1970,23 +1970,24 @@ compiler_if(struct compiler *c, stmt_ty s) static int compiler_for(struct compiler *c, stmt_ty s) { - basicblock *start, *cleanup, *end; + basicblock *start, *cleanup, *end, *contstart; start = compiler_new_block(c); + contstart = compiler_new_block(c); cleanup = compiler_new_block(c); end = compiler_new_block(c); - if (start == NULL || end == NULL || cleanup == NULL) + if (start == NULL || contstart == NULL || end == NULL || cleanup == NULL) return 0; ADDOP_JREL(c, SETUP_LOOP, end); - if (!compiler_push_fblock(c, LOOP, start)) + if (!compiler_push_fblock(c, LOOP, contstart)) return 0; VISIT(c, expr, s->v.For.iter); - ADDOP(c, GET_ITER); + ADDOP_JREL(c, FOR_BEGIN, cleanup); compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, cleanup); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); + compiler_use_next_block(c, contstart); + ADDOP_JABS(c, FOR_ITER, start); compiler_use_next_block(c, cleanup); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, LOOP, start); @@ -3425,17 +3426,16 @@ compiler_comprehension_generator(struct compiler *c, gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); if (gen_index == 0) { - /* Receive outermost iter as an implicit argument */ + /* Receive outermost iterable as an implicit argument */ c->u->u_argcount = 1; ADDOP_I(c, LOAD_FAST, 0); } else { /* Sub-iter - calculate on the fly */ VISIT(c, expr, gen->iter); - ADDOP(c, GET_ITER); } + ADDOP_JREL(c, FOR_BEGIN, anchor); compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, anchor); NEXT_BLOCK(c); VISIT(c, expr, gen->target); @@ -3485,7 +3485,7 @@ compiler_comprehension_generator(struct compiler *c, compiler_use_next_block(c, skip); } compiler_use_next_block(c, if_cleanup); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); + ADDOP_JABS(c, FOR_ITER, start); compiler_use_next_block(c, anchor); return 1; @@ -3549,7 +3549,6 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, Py_DECREF(co); VISIT(c, expr, outermost_iter); - ADDOP(c, GET_ITER); ADDOP_I(c, CALL_FUNCTION, 1); return 1; error_in_scope: @@ -4320,9 +4319,12 @@ stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) assert(depth >= 0); /* invalid code or bug in stackdepth() */ if (instr->i_jrel || instr->i_jabs) { target_depth = depth; - if (instr->i_opcode == FOR_ITER) { + if (instr->i_opcode == FOR_BEGIN) { target_depth = depth-2; } + else if (instr->i_opcode == FOR_ITER) { + depth -= 2; + } else if (instr->i_opcode == SETUP_FINALLY || instr->i_opcode == SETUP_EXCEPT) { target_depth = depth+3; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 3872256..bbe1860 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -67,7 +67,7 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_XOR, &&TARGET_BINARY_OR, &&TARGET_INPLACE_POWER, - &&TARGET_GET_ITER, + &&_unknown_opcode, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, @@ -98,7 +98,7 @@ static void *opcode_targets[256] = { &&TARGET_DELETE_ATTR, &&TARGET_STORE_GLOBAL, &&TARGET_DELETE_GLOBAL, - &&_unknown_opcode, + &&TARGET_FOR_BEGIN, &&TARGET_LOAD_CONST, &&TARGET_LOAD_NAME, &&TARGET_BUILD_TUPLE, diff --git a/Python/peephole.c b/Python/peephole.c index 62625f7..94f5f47 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -15,7 +15,7 @@ || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) #define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \ || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ - || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) + || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP || op==FOR_ITER) #define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP) #define GETJUMPTGT(arr, i) (get_arg(arr, i) + (ABSOLUTE_JUMP(arr[i]) ? 0 : i+2)) #define ISBASICBLOCK(blocks, start, end) \ @@ -104,25 +104,6 @@ find_op(unsigned char *codestr, Py_ssize_t i) } /* Given the index of the effective opcode, - scan back to construct the oparg with EXTENDED_ARG */ -static unsigned int -get_arg(unsigned char *codestr, Py_ssize_t i) -{ - unsigned int oparg = codestr[i+1]; - assert((i&1) == 0); - if (i >= 2 && codestr[i-2] == EXTENDED_ARG) { - oparg |= codestr[i-1] << 8; - if (i >= 4 && codestr[i-4] == EXTENDED_ARG) { - oparg |= codestr[i-3] << 16; - if (i >= 6 && codestr[i-6] == EXTENDED_ARG) { - oparg |= codestr[i-5] << 24; - } - } - } - return oparg; -} - -/* Given the index of the effective opcode, attempt to replace the argument, taking into account EXTENDED_ARG. Returns -1 on failure, or the new op index on success */ static Py_ssize_t @@ -374,6 +355,7 @@ markblocks(unsigned char *code, Py_ssize_t len) for (i=0 ; i= 0) { @@ -670,6 +652,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Replace jumps to unconditional jumps */ case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: + case FOR_BEGIN: case FOR_ITER: case JUMP_FORWARD: case JUMP_ABSOLUTE: @@ -747,6 +730,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, switch (opcode) { case NOP:continue; + case FOR_ITER: case JUMP_ABSOLUTE: case CONTINUE_LOOP: case POP_JUMP_IF_FALSE: @@ -756,7 +740,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, j = blocks[j]; break; - case FOR_ITER: + case FOR_BEGIN: case JUMP_FORWARD: case SETUP_LOOP: case SETUP_EXCEPT: diff --git a/Python/wordcode_helpers.h b/Python/wordcode_helpers.h index b61ba33..f6126e5 100644 --- a/Python/wordcode_helpers.h +++ b/Python/wordcode_helpers.h @@ -3,7 +3,7 @@ */ /* Minimum number of bytes necessary to encode instruction with EXTENDED_ARGs */ -static int +Py_LOCAL_INLINE(int) instrsize(unsigned int oparg) { return oparg <= 0xff ? 2 : @@ -14,7 +14,7 @@ instrsize(unsigned int oparg) /* Spits out op/oparg pair using ilen bytes. codestr should be pointed at the desired location of the first EXTENDED_ARG */ -static void +Py_LOCAL_INLINE(void) write_op_arg(unsigned char *codestr, unsigned char opcode, unsigned int oparg, int ilen) { @@ -36,3 +36,23 @@ write_op_arg(unsigned char *codestr, unsigned char opcode, assert(0); } } + +/* Given the index of the effective opcode, + scan back to construct the oparg with EXTENDED_ARG */ +Py_LOCAL_INLINE(unsigned int) +get_arg(unsigned char *codestr, Py_ssize_t i) +{ + unsigned int oparg = codestr[i+1]; + assert((i&1) == 0); + if (i >= 2 && codestr[i-2] == EXTENDED_ARG) { + oparg |= codestr[i-1] << 8; + if (i >= 4 && codestr[i-4] == EXTENDED_ARG) { + oparg |= codestr[i-3] << 16; + if (i >= 6 && codestr[i-6] == EXTENDED_ARG) { + oparg |= codestr[i-5] << 24; + } + } + } + return oparg; +} +