bpo-39156: Break up COMPARE_OP into four logically distinct opcodes. (GH-17754)

Break up COMPARE_OP into four logically distinct opcodes:
* COMPARE_OP for rich comparisons
* IS_OP for 'is' and 'is not' tests
* CONTAINS_OP for 'in' and 'is not' tests
* JUMP_IF_NOT_EXC_MATCH for checking exceptions in 'try-except' statements.
This commit is contained in:
Mark Shannon 2020-01-14 10:12:45 +00:00 committed by GitHub
parent 62e3973395
commit 9af0e47b17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 4909 additions and 4855 deletions

View file

@ -927,6 +927,20 @@ All of the following opcodes use their arguments.
``cmp_op[opname]``. ``cmp_op[opname]``.
.. opcode:: IS_OP (invert)
Performs ``is`` comparison, or ``is not`` if ``invert`` is 1.
.. versionadded:: 3.9
.. opcode:: CONTAINS_OP (invert)
Performs ``in`` comparison, or ``not in`` if ``invert`` is 1.
.. versionadded:: 3.9
.. opcode:: IMPORT_NAME (namei) .. opcode:: IMPORT_NAME (namei)
Imports the module ``co_names[namei]``. TOS and TOS1 are popped and provide Imports the module ``co_names[namei]``. TOS and TOS1 are popped and provide
@ -961,6 +975,13 @@ All of the following opcodes use their arguments.
.. versionadded:: 3.1 .. versionadded:: 3.1
.. opcode:: JUMP_IF_NOT_EXC_MATCH (target)
Tests whether the second value on the stack is an exception matching TOS,
and jumps if it is not. Pops two values from the stack.
.. versionadded:: 3.9
.. opcode:: JUMP_IF_TRUE_OR_POP (target) .. opcode:: JUMP_IF_TRUE_OR_POP (target)

8
Include/opcode.h generated
View file

@ -93,6 +93,9 @@ extern "C" {
#define POP_JUMP_IF_FALSE 114 #define POP_JUMP_IF_FALSE 114
#define POP_JUMP_IF_TRUE 115 #define POP_JUMP_IF_TRUE 115
#define LOAD_GLOBAL 116 #define LOAD_GLOBAL 116
#define IS_OP 117
#define CONTAINS_OP 118
#define JUMP_IF_NOT_EXC_MATCH 121
#define SETUP_FINALLY 122 #define SETUP_FINALLY 122
#define LOAD_FAST 124 #define LOAD_FAST 124
#define STORE_FAST 125 #define STORE_FAST 125
@ -132,11 +135,6 @@ extern "C" {
remaining private.*/ remaining private.*/
#define EXCEPT_HANDLER 257 #define EXCEPT_HANDLER 257
enum cmp_op {PyCmp_LT=Py_LT, PyCmp_LE=Py_LE, PyCmp_EQ=Py_EQ, PyCmp_NE=Py_NE,
PyCmp_GT=Py_GT, PyCmp_GE=Py_GE, PyCmp_IN, PyCmp_NOT_IN,
PyCmp_IS, PyCmp_IS_NOT, PyCmp_EXC_MATCH, PyCmp_BAD};
#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -274,6 +274,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.9a0 3420 (add LOAD_ASSERTION_ERROR #34880) # Python 3.9a0 3420 (add LOAD_ASSERTION_ERROR #34880)
# Python 3.9a0 3421 (simplified bytecode for with blocks #32949) # Python 3.9a0 3421 (simplified bytecode for with blocks #32949)
# Python 3.9a0 3422 (remove BEGIN_FINALLY, END_FINALLY, CALL_FINALLY, POP_FINALLY bytecodes #33387) # Python 3.9a0 3422 (remove BEGIN_FINALLY, END_FINALLY, CALL_FINALLY, POP_FINALLY bytecodes #33387)
# Python 3.9a2 3423 (add IS_OP, CONTAINS_OP and JUMP_IF_NOT_EXC_MATCH bytecodes #39156)
# #
# MAGIC must change whenever the bytecode emitted by the compiler may no # MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually # longer be understood by older implementations of the eval loop (usually
@ -282,7 +283,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated. # in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3422).to_bytes(2, 'little') + b'\r\n' MAGIC_NUMBER = (3423).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__' _PYCACHE = '__pycache__'

View file

@ -21,8 +21,7 @@
except ImportError: except ImportError:
pass pass
cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', cmp_op = ('<', '<=', '==', '!=', '>', '>=')
'is not', 'exception match', 'BAD')
hasconst = [] hasconst = []
hasname = [] hasname = []
@ -159,6 +158,10 @@ def jabs_op(name, op):
name_op('LOAD_GLOBAL', 116) # Index in name list name_op('LOAD_GLOBAL', 116) # Index in name list
def_op('IS_OP', 117)
def_op('CONTAINS_OP', 118)
jabs_op('JUMP_IF_NOT_EXC_MATCH', 121)
jrel_op('SETUP_FINALLY', 122) # Distance to target address jrel_op('SETUP_FINALLY', 122) # Distance to target address
def_op('LOAD_FAST', 124) # Local variable number def_op('LOAD_FAST', 124) # Local variable number

View file

@ -278,34 +278,33 @@ def bug1333982(x=[]):
--> 6 BINARY_TRUE_DIVIDE --> 6 BINARY_TRUE_DIVIDE
8 POP_TOP 8 POP_TOP
10 POP_BLOCK 10 POP_BLOCK
12 JUMP_FORWARD 44 (to 58) 12 JUMP_FORWARD 42 (to 56)
%3d >> 14 DUP_TOP %3d >> 14 DUP_TOP
16 LOAD_GLOBAL 0 (Exception) 16 LOAD_GLOBAL 0 (Exception)
18 COMPARE_OP 10 (exception match) 18 JUMP_IF_NOT_EXC_MATCH 54
20 POP_JUMP_IF_FALSE 56 20 POP_TOP
22 POP_TOP 22 STORE_FAST 0 (e)
24 STORE_FAST 0 (e) 24 POP_TOP
26 POP_TOP 26 SETUP_FINALLY 18 (to 46)
28 SETUP_FINALLY 18 (to 48)
%3d 30 LOAD_FAST 0 (e) %3d 28 LOAD_FAST 0 (e)
32 LOAD_ATTR 1 (__traceback__) 30 LOAD_ATTR 1 (__traceback__)
34 STORE_FAST 1 (tb) 32 STORE_FAST 1 (tb)
36 POP_BLOCK 34 POP_BLOCK
38 POP_EXCEPT 36 POP_EXCEPT
40 LOAD_CONST 0 (None) 38 LOAD_CONST 0 (None)
42 STORE_FAST 0 (e) 40 STORE_FAST 0 (e)
44 DELETE_FAST 0 (e) 42 DELETE_FAST 0 (e)
46 JUMP_FORWARD 10 (to 58) 44 JUMP_FORWARD 10 (to 56)
>> 48 LOAD_CONST 0 (None) >> 46 LOAD_CONST 0 (None)
50 STORE_FAST 0 (e) 48 STORE_FAST 0 (e)
52 DELETE_FAST 0 (e) 50 DELETE_FAST 0 (e)
54 RERAISE 52 RERAISE
>> 56 RERAISE >> 54 RERAISE
%3d >> 58 LOAD_FAST 1 (tb) %3d >> 56 LOAD_FAST 1 (tb)
60 RETURN_VALUE 58 RETURN_VALUE
""" % (TRACEBACK_CODE.co_firstlineno + 1, """ % (TRACEBACK_CODE.co_firstlineno + 1,
TRACEBACK_CODE.co_firstlineno + 2, TRACEBACK_CODE.co_firstlineno + 2,
TRACEBACK_CODE.co_firstlineno + 3, TRACEBACK_CODE.co_firstlineno + 3,
@ -506,7 +505,8 @@ def test_boundaries(self):
def test_widths(self): def test_widths(self):
for opcode, opname in enumerate(dis.opname): for opcode, opname in enumerate(dis.opname):
if opname in ('BUILD_MAP_UNPACK_WITH_CALL', if opname in ('BUILD_MAP_UNPACK_WITH_CALL',
'BUILD_TUPLE_UNPACK_WITH_CALL'): 'BUILD_TUPLE_UNPACK_WITH_CALL',
'JUMP_IF_NOT_EXC_MATCH'):
continue continue
with self.subTest(opname=opname): with self.subTest(opname=opname):
width = dis._OPNAME_WIDTH width = dis._OPNAME_WIDTH
@ -1045,63 +1045,62 @@ def jumpy():
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='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='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=98, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=100, starts_line=None, is_jump_target=False), 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=98, argval=202, argrepr='to 202', offset=102, starts_line=20, is_jump_target=True), Instruction(opname='SETUP_FINALLY', opcode=122, arg=96, argval=200, argrepr='to 200', offset=102, starts_line=20, is_jump_target=True),
Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, 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=5, argval=1, argrepr='1', offset=106, starts_line=21, 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='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, 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='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, 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_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, 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='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, 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='JUMP_FORWARD', opcode=110, arg=28, argval=146, argrepr='to 146', offset=116, starts_line=None, is_jump_target=False), Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=144, argrepr='to 144', 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='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=118, starts_line=22, is_jump_target=True),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=120, 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='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=122, 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_JUMP_IF_FALSE', opcode=114, arg=144, argval=144, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, 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='POP_TOP', opcode=1, arg=None, argval=None, 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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=130, starts_line=23, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, 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=132, 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=134, 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='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, 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='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False), Instruction(opname='JUMP_FORWARD', opcode=110, arg=46, argval=188, argrepr='to 188', offset=140, starts_line=None, is_jump_target=False),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=46, argval=190, argrepr='to 190', offset=142, starts_line=None, is_jump_target=False), Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=True),
Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=True), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=25, is_jump_target=True), Instruction(opname='SETUP_WITH', opcode=143, arg=24, argval=172, argrepr='to 172', offset=146, starts_line=None, is_jump_target=False),
Instruction(opname='SETUP_WITH', opcode=143, arg=24, argval=174, argrepr='to 174', offset=148, starts_line=None, 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='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, 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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, 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='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, 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='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, 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='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, 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='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=162, 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='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=164, 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='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=166, 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='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=168, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False), Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=188, argrepr='to 188', offset=170, starts_line=None, is_jump_target=False),
Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=190, argrepr='to 190', offset=172, 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='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=True), 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_JUMP_IF_TRUE', opcode=115, arg=180, argval=180, argrepr='', offset=176, starts_line=None, is_jump_target=False), Instruction(opname='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False),
Instruction(opname='RERAISE', opcode=48, 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=178, starts_line=None, is_jump_target=True),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=True), Instruction(opname='POP_TOP', opcode=1, 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_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, 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_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, 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='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=True), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=190, starts_line=28, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, 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='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, 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='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, 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='JUMP_FORWARD', opcode=110, arg=10, argval=212, argrepr='to 212', offset=200, starts_line=None, is_jump_target=False), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=200, starts_line=None, is_jump_target=True),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=202, 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=202, 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=204, 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='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=206, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=208, 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='RERAISE', opcode=48, arg=None, argval=None, argrepr='', offset=210, 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='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=212, 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),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=214, 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

View file

@ -65,14 +65,14 @@ def unot(x):
self.check_lnotab(unot) self.check_lnotab(unot)
def test_elim_inversion_of_is_or_in(self): def test_elim_inversion_of_is_or_in(self):
for line, cmp_op in ( for line, cmp_op, invert in (
('not a is b', 'is not',), ('not a is b', 'IS_OP', 1,),
('not a in b', 'not in',), ('not a is not b', 'IS_OP', 0,),
('not a is not b', 'is',), ('not a in b', 'CONTAINS_OP', 1,),
('not a not in b', 'in',), ('not a not in b', 'CONTAINS_OP', 0,),
): ):
code = compile(line, '', 'single') code = compile(line, '', 'single')
self.assertInBytecode(code, 'COMPARE_OP', cmp_op) self.assertInBytecode(code, cmp_op, invert)
self.check_lnotab(code) self.check_lnotab(code)
def test_global_as_constant(self): def test_global_as_constant(self):

View file

@ -434,11 +434,11 @@ def g():
def f(x: not (int is int), /): ... def f(x: not (int is int), /): ...
# without constant folding we end up with # without constant folding we end up with
# COMPARE_OP(is), UNARY_NOT # COMPARE_OP(is), IS_OP (0)
# with constant folding we should expect a COMPARE_OP(is not) # with constant folding we should expect a IS_OP (1)
codes = [(i.opname, i.argval) for i in dis.get_instructions(g)] codes = [(i.opname, i.argval) for i in dis.get_instructions(g)]
self.assertNotIn(('UNARY_NOT', None), codes) self.assertNotIn(('UNARY_NOT', None), codes)
self.assertIn(('COMPARE_OP', 'is not'), codes) self.assertIn(('IS_OP', 1), codes)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -0,0 +1,9 @@
Split the COMPARE_OP bytecode instruction into four distinct instructions.
* COMPARE_OP for rich comparisons
* IS_OP for 'is' and 'is not' tests
* CONTAINS_OP for 'in' and 'is not' tests
* JUMP_IF_NOT_EXC_MATCH for checking exceptions in 'try-except' statements.
This improves the clarity of the interpreter and should provide a modest
speedup.

View file

@ -1247,6 +1247,7 @@ static PYC_MAGIC magic_values[] = {
{ 3360, 3379, L"3.6" }, { 3360, 3379, L"3.6" },
{ 3390, 3399, L"3.7" }, { 3390, 3399, L"3.7" },
{ 3400, 3419, L"3.8" }, { 3400, 3419, L"3.8" },
{ 3420, 3429, L"3.9" },
{ 0 } { 0 }
}; };
@ -1830,7 +1831,7 @@ process(int argc, wchar_t ** argv)
#if !defined(VENV_REDIRECT) #if !defined(VENV_REDIRECT)
/* bpo-35811: The __PYVENV_LAUNCHER__ variable is used to /* bpo-35811: The __PYVENV_LAUNCHER__ variable is used to
* override sys.executable and locate the original prefix path. * override sys.executable and locate the original prefix path.
* However, if it is silently inherited by a non-venv Python * However, if it is silently inherited by a non-venv Python
* process, that process will believe it is running in the venv * process, that process will believe it is running in the venv
* still. This is the only place where *we* can clear it (that is, * still. This is the only place where *we* can clear it (that is,

View file

@ -67,7 +67,6 @@ static void maybe_dtrace_line(PyFrameObject *, int *, int *, int *);
static void dtrace_function_entry(PyFrameObject *); static void dtrace_function_entry(PyFrameObject *);
static void dtrace_function_return(PyFrameObject *); static void dtrace_function_return(PyFrameObject *);
static PyObject * cmp_outcome(PyThreadState *, int, PyObject *, PyObject *);
static PyObject * import_name(PyThreadState *, PyFrameObject *, static PyObject * import_name(PyThreadState *, PyFrameObject *,
PyObject *, PyObject *, PyObject *); PyObject *, PyObject *, PyObject *);
static PyObject * import_from(PyThreadState *, PyObject *, PyObject *); static PyObject * import_from(PyThreadState *, PyObject *, PyObject *);
@ -2897,12 +2896,13 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
} }
case TARGET(COMPARE_OP): { case TARGET(COMPARE_OP): {
assert(oparg <= Py_GE);
PyObject *right = POP(); PyObject *right = POP();
PyObject *left = TOP(); PyObject *left = TOP();
PyObject *res = cmp_outcome(tstate, oparg, left, right); PyObject *res = PyObject_RichCompare(left, right, oparg);
SET_TOP(res);
Py_DECREF(left); Py_DECREF(left);
Py_DECREF(right); Py_DECREF(right);
SET_TOP(res);
if (res == NULL) if (res == NULL)
goto error; goto error;
PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_FALSE);
@ -2910,6 +2910,81 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
DISPATCH(); DISPATCH();
} }
case TARGET(IS_OP): {
PyObject *right = POP();
PyObject *left = TOP();
int res = (left == right)^oparg;
PyObject *b = res ? Py_True : Py_False;
Py_INCREF(b);
SET_TOP(b);
Py_DECREF(left);
Py_DECREF(right);
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
FAST_DISPATCH();
}
case TARGET(CONTAINS_OP): {
PyObject *right = POP();
PyObject *left = POP();
int res = PySequence_Contains(right, left);
Py_DECREF(left);
Py_DECREF(right);
if (res < 0) {
goto error;
}
PyObject *b = (res^oparg) ? Py_True : Py_False;
Py_INCREF(b);
PUSH(b);
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
FAST_DISPATCH();
}
#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
"BaseException is not allowed"
case TARGET(JUMP_IF_NOT_EXC_MATCH): {
PyObject *right = POP();
PyObject *left = POP();
if (PyTuple_Check(right)) {
Py_ssize_t i, length;
length = PyTuple_GET_SIZE(right);
for (i = 0; i < length; i++) {
PyObject *exc = PyTuple_GET_ITEM(right, i);
if (!PyExceptionClass_Check(exc)) {
_PyErr_SetString(tstate, PyExc_TypeError,
CANNOT_CATCH_MSG);
Py_DECREF(left);
Py_DECREF(right);
goto error;
}
}
}
else {
if (!PyExceptionClass_Check(right)) {
_PyErr_SetString(tstate, PyExc_TypeError,
CANNOT_CATCH_MSG);
Py_DECREF(left);
Py_DECREF(right);
goto error;
}
}
int res = PyErr_GivenExceptionMatches(left, right);
Py_DECREF(left);
Py_DECREF(right);
if (res > 0) {
/* Exception matches -- Do nothing */;
}
else if (res == 0) {
JUMPTO(oparg);
}
else {
goto error;
}
DISPATCH();
}
case TARGET(IMPORT_NAME): { case TARGET(IMPORT_NAME): {
PyObject *name = GETITEM(names, oparg); PyObject *name = GETITEM(names, oparg);
PyObject *fromlist = POP(); PyObject *fromlist = POP();
@ -4951,62 +5026,6 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
return 1; return 1;
} }
#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
"BaseException is not allowed"
static PyObject *
cmp_outcome(PyThreadState *tstate, int op, PyObject *v, PyObject *w)
{
int res = 0;
switch (op) {
case PyCmp_IS:
res = (v == w);
break;
case PyCmp_IS_NOT:
res = (v != w);
break;
case PyCmp_IN:
res = PySequence_Contains(w, v);
if (res < 0)
return NULL;
break;
case PyCmp_NOT_IN:
res = PySequence_Contains(w, v);
if (res < 0)
return NULL;
res = !res;
break;
case PyCmp_EXC_MATCH:
if (PyTuple_Check(w)) {
Py_ssize_t i, length;
length = PyTuple_Size(w);
for (i = 0; i < length; i += 1) {
PyObject *exc = PyTuple_GET_ITEM(w, i);
if (!PyExceptionClass_Check(exc)) {
_PyErr_SetString(tstate, PyExc_TypeError,
CANNOT_CATCH_MSG);
return NULL;
}
}
}
else {
if (!PyExceptionClass_Check(w)) {
_PyErr_SetString(tstate, PyExc_TypeError,
CANNOT_CATCH_MSG);
return NULL;
}
}
res = PyErr_GivenExceptionMatches(v, w);
break;
default:
return PyObject_RichCompare(v, w, op);
}
v = res ? Py_True : Py_False;
Py_INCREF(v);
return v;
}
static PyObject * static PyObject *
import_name(PyThreadState *tstate, PyFrameObject *f, import_name(PyThreadState *tstate, PyFrameObject *f,
PyObject *name, PyObject *fromlist, PyObject *level) PyObject *name, PyObject *fromlist, PyObject *level)

View file

@ -1021,7 +1021,11 @@ stack_effect(int opcode, int oparg, int jump)
case LOAD_ATTR: case LOAD_ATTR:
return 0; return 0;
case COMPARE_OP: case COMPARE_OP:
case IS_OP:
case CONTAINS_OP:
return -1; return -1;
case JUMP_IF_NOT_EXC_MATCH:
return -2;
case IMPORT_NAME: case IMPORT_NAME:
return -1; return -1;
case IMPORT_FROM: case IMPORT_FROM:
@ -1502,6 +1506,12 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
return 0; \ return 0; \
} }
#define ADDOP_COMPARE(C, CMP) { \
if (!compiler_addcompare((C), (cmpop_ty)(CMP))) \
return 0; \
}
/* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use /* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use
the ASDL name to synthesize the name of the C type and the visit function. the ASDL name to synthesize the name of the C type and the visit function.
*/ */
@ -2433,35 +2443,49 @@ check_compare(struct compiler *c, expr_ty e)
return 1; return 1;
} }
static int static int compiler_addcompare(struct compiler *c, cmpop_ty op)
cmpop(cmpop_ty op)
{ {
int cmp;
switch (op) { switch (op) {
case Eq: case Eq:
return PyCmp_EQ; cmp = Py_EQ;
break;
case NotEq: case NotEq:
return PyCmp_NE; cmp = Py_NE;
break;
case Lt: case Lt:
return PyCmp_LT; cmp = Py_LT;
break;
case LtE: case LtE:
return PyCmp_LE; cmp = Py_LE;
break;
case Gt: case Gt:
return PyCmp_GT; cmp = Py_GT;
break;
case GtE: case GtE:
return PyCmp_GE; cmp = Py_GE;
break;
case Is: case Is:
return PyCmp_IS; ADDOP_I(c, IS_OP, 0);
return 1;
case IsNot: case IsNot:
return PyCmp_IS_NOT; ADDOP_I(c, IS_OP, 1);
return 1;
case In: case In:
return PyCmp_IN; ADDOP_I(c, CONTAINS_OP, 0);
return 1;
case NotIn: case NotIn:
return PyCmp_NOT_IN; ADDOP_I(c, CONTAINS_OP, 1);
return 1;
default: default:
return PyCmp_BAD; Py_UNREACHABLE();
} }
ADDOP_I(c, COMPARE_OP, cmp);
return 1;
} }
static int static int
compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
{ {
@ -2526,14 +2550,12 @@ compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond)
(expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP);
ADDOP(c, ROT_THREE); ADDOP(c, ROT_THREE);
ADDOP_I(c, COMPARE_OP, ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, i))));
ADDOP_JABS(c, POP_JUMP_IF_FALSE, cleanup); ADDOP_JABS(c, POP_JUMP_IF_FALSE, cleanup);
NEXT_BLOCK(c); NEXT_BLOCK(c);
} }
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
ADDOP_I(c, COMPARE_OP, ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n));
cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n))));
ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next);
basicblock *end = compiler_new_block(c); basicblock *end = compiler_new_block(c);
if (end == NULL) if (end == NULL)
@ -2976,8 +2998,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s)
[tb, val, exc] L1: DUP ) [tb, val, exc] L1: DUP )
[tb, val, exc, exc] <evaluate E1> ) [tb, val, exc, exc] <evaluate E1> )
[tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 [tb, val, exc, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1
[tb, val, exc, 1-or-0] POP_JUMP_IF_FALSE L2 )
[tb, val, exc] POP [tb, val, exc] POP
[tb, val] <assign to V1> (or POP if no V1) [tb, val] <assign to V1> (or POP if no V1)
[tb] POP [tb] POP
@ -3029,8 +3050,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
if (handler->v.ExceptHandler.type) { if (handler->v.ExceptHandler.type) {
ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP);
VISIT(c, expr, handler->v.ExceptHandler.type); VISIT(c, expr, handler->v.ExceptHandler.type);
ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); ADDOP_JABS(c, JUMP_IF_NOT_EXC_MATCH, except);
ADDOP_JABS(c, POP_JUMP_IF_FALSE, except);
} }
ADDOP(c, POP_TOP); ADDOP(c, POP_TOP);
if (handler->v.ExceptHandler.name) { if (handler->v.ExceptHandler.name) {
@ -3873,8 +3893,7 @@ compiler_compare(struct compiler *c, expr_ty e)
n = asdl_seq_LEN(e->v.Compare.ops) - 1; n = asdl_seq_LEN(e->v.Compare.ops) - 1;
if (n == 0) { if (n == 0) {
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0));
ADDOP_I(c, COMPARE_OP, ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, 0));
cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, 0))));
} }
else { else {
basicblock *cleanup = compiler_new_block(c); basicblock *cleanup = compiler_new_block(c);
@ -3885,14 +3904,12 @@ compiler_compare(struct compiler *c, expr_ty e)
(expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i));
ADDOP(c, DUP_TOP); ADDOP(c, DUP_TOP);
ADDOP(c, ROT_THREE); ADDOP(c, ROT_THREE);
ADDOP_I(c, COMPARE_OP, ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, i));
cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, i))));
ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup);
NEXT_BLOCK(c); NEXT_BLOCK(c);
} }
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n));
ADDOP_I(c, COMPARE_OP, ADDOP_COMPARE(c, asdl_seq_GET(e->v.Compare.ops, n));
cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n))));
basicblock *end = compiler_new_block(c); basicblock *end = compiler_new_block(c);
if (end == NULL) if (end == NULL)
return 0; return 0;

2930
Python/importlib.h generated

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

View file

@ -116,11 +116,11 @@ static void *opcode_targets[256] = {
&&TARGET_POP_JUMP_IF_FALSE, &&TARGET_POP_JUMP_IF_FALSE,
&&TARGET_POP_JUMP_IF_TRUE, &&TARGET_POP_JUMP_IF_TRUE,
&&TARGET_LOAD_GLOBAL, &&TARGET_LOAD_GLOBAL,
&&TARGET_IS_OP,
&&TARGET_CONTAINS_OP,
&&_unknown_opcode, &&_unknown_opcode,
&&_unknown_opcode, &&_unknown_opcode,
&&_unknown_opcode, &&TARGET_JUMP_IF_NOT_EXC_MATCH,
&&_unknown_opcode,
&&_unknown_opcode,
&&TARGET_SETUP_FINALLY, &&TARGET_SETUP_FINALLY,
&&_unknown_opcode, &&_unknown_opcode,
&&TARGET_LOAD_FAST, &&TARGET_LOAD_FAST,

View file

@ -12,10 +12,10 @@
#define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) #define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD)
#define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ #define CONDITIONAL_JUMP(op) (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==JUMP_IF_NOT_EXC_MATCH)
#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE \ #define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE \
|| op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ || 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==JUMP_IF_NOT_EXC_MATCH)
#define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP) #define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP)
#define GETJUMPTGT(arr, i) (get_arg(arr, i) / sizeof(_Py_CODEUNIT) + \ #define GETJUMPTGT(arr, i) (get_arg(arr, i) / sizeof(_Py_CODEUNIT) + \
(ABSOLUTE_JUMP(_Py_OPCODE(arr[i])) ? 0 : i+1)) (ABSOLUTE_JUMP(_Py_OPCODE(arr[i])) ? 0 : i+1))
@ -194,6 +194,7 @@ markblocks(_Py_CODEUNIT *code, Py_ssize_t len)
case JUMP_IF_TRUE_OR_POP: case JUMP_IF_TRUE_OR_POP:
case POP_JUMP_IF_FALSE: case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE: case POP_JUMP_IF_TRUE:
case JUMP_IF_NOT_EXC_MATCH:
case JUMP_ABSOLUTE: case JUMP_ABSOLUTE:
case SETUP_FINALLY: case SETUP_FINALLY:
case SETUP_WITH: case SETUP_WITH:
@ -493,6 +494,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
case POP_JUMP_IF_TRUE: case POP_JUMP_IF_TRUE:
case JUMP_IF_FALSE_OR_POP: case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP: case JUMP_IF_TRUE_OR_POP:
case JUMP_IF_NOT_EXC_MATCH:
j = blocks[j / sizeof(_Py_CODEUNIT)] * sizeof(_Py_CODEUNIT); j = blocks[j / sizeof(_Py_CODEUNIT)] * sizeof(_Py_CODEUNIT);
break; break;

View file

@ -22,11 +22,6 @@
remaining private.*/ remaining private.*/
#define EXCEPT_HANDLER 257 #define EXCEPT_HANDLER 257
enum cmp_op {PyCmp_LT=Py_LT, PyCmp_LE=Py_LE, PyCmp_EQ=Py_EQ, PyCmp_NE=Py_NE,
PyCmp_GT=Py_GT, PyCmp_GE=Py_GE, PyCmp_IN, PyCmp_NOT_IN,
PyCmp_IS, PyCmp_IS_NOT, PyCmp_EXC_MATCH, PyCmp_BAD};
#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT) #define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
#ifdef __cplusplus #ifdef __cplusplus