mirror of https://github.com/python/cpython
bpo-47120: make POP_JUMP_IF_TRUE/FALSE/NONE/NOT_NONE relative (GH-32400)
This commit is contained in:
parent
98ff4a6877
commit
dd207a6ac5
|
@ -937,30 +937,58 @@ iterations of the loop.
|
|||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_IF_TRUE (target)
|
||||
.. opcode:: POP_JUMP_FORWARD_IF_TRUE (delta)
|
||||
|
||||
If TOS is true, sets the bytecode counter to *target*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_IF_FALSE (target)
|
||||
|
||||
If TOS is false, sets the bytecode counter to *target*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_IF_NOT_NONE (target)
|
||||
|
||||
If TOS is not none, sets the bytecode counter to *target*. TOS is popped.
|
||||
If TOS is true, increments the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_IF_NONE (target)
|
||||
.. opcode:: POP_JUMP_BACKWARD_IF_TRUE (delta)
|
||||
|
||||
If TOS is none, sets the bytecode counter to *target*. TOS is popped.
|
||||
If TOS is true, decrements the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_FORWARD_IF_FALSE (delta)
|
||||
|
||||
If TOS is false, increments the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_BACKWARD_IF_FALSE (delta)
|
||||
|
||||
If TOS is false, decrements the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_FORWARD_IF_NOT_NONE (delta)
|
||||
|
||||
If TOS is not ``None``, increments the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_BACKWARD_IF_NOT_NONE (delta)
|
||||
|
||||
If TOS is not ``None``, decrements the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_FORWARD_IF_NONE (delta)
|
||||
|
||||
If TOS is ``None``, increments the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
||||
.. opcode:: POP_JUMP_BACKWARD_IF_NONE (delta)
|
||||
|
||||
If TOS is ``None``, decrements the bytecode counter by *delta*. TOS is popped.
|
||||
|
||||
.. versionadded:: 3.11
|
||||
|
||||
|
|
|
@ -750,9 +750,6 @@ CPython bytecode changes
|
|||
``ROT_TWO``, ``ROT_THREE``, ``ROT_FOUR``, and ``ROT_N``) with new
|
||||
:opcode:`COPY` and :opcode:`SWAP` instructions.
|
||||
|
||||
* Add :opcode:`POP_JUMP_IF_NOT_NONE` and :opcode:`POP_JUMP_IF_NONE` opcodes to
|
||||
speed up conditional jumps.
|
||||
|
||||
* Replaced :opcode:`JUMP_IF_NOT_EXC_MATCH` by :opcode:`CHECK_EXC_MATCH` which
|
||||
performs the check but does not jump.
|
||||
|
||||
|
@ -761,7 +758,17 @@ CPython bytecode changes
|
|||
|
||||
* Replaced :opcode:`JUMP_ABSOLUTE` by the relative :opcode:`JUMP_BACKWARD`.
|
||||
|
||||
* Added :opcode:`JUMP_BACKWARD_NO_INTERRUPT`, which is used in certain loops where it is undesirable to handle interrupts.
|
||||
* Added :opcode:`JUMP_BACKWARD_NO_INTERRUPT`, which is used in certain loops where it
|
||||
is undesirable to handle interrupts.
|
||||
|
||||
* Replaced :opcode:`POP_JUMP_IF_TRUE` and :opcode:`POP_JUMP_IF_FALSE` by
|
||||
the relative :opcode:`POP_JUMP_FORWARD_IF_TRUE`, :opcode:`POP_JUMP_BACKWARD_IF_TRUE`,
|
||||
:opcode:`POP_JUMP_FORWARD_IF_FALSE` and :opcode:`POP_JUMP_BACKWARD_IF_FALSE`.
|
||||
|
||||
* Added :opcode:`POP_JUMP_FORWARD_IF_NOT_NONE`, :opcode:`POP_JUMP_BACKWARD_IF_NOT_NONE`,
|
||||
:opcode:`POP_JUMP_FORWARD_IF_NONE` and :opcode:`POP_JUMP_BACKWARD_IF_NONE`
|
||||
opcodes to speed up conditional jumps.
|
||||
|
||||
|
||||
Deprecated
|
||||
==========
|
||||
|
|
|
@ -69,8 +69,8 @@ extern "C" {
|
|||
#define JUMP_FORWARD 110
|
||||
#define JUMP_IF_FALSE_OR_POP 111
|
||||
#define JUMP_IF_TRUE_OR_POP 112
|
||||
#define POP_JUMP_IF_FALSE 114
|
||||
#define POP_JUMP_IF_TRUE 115
|
||||
#define POP_JUMP_FORWARD_IF_FALSE 114
|
||||
#define POP_JUMP_FORWARD_IF_TRUE 115
|
||||
#define LOAD_GLOBAL 116
|
||||
#define IS_OP 117
|
||||
#define CONTAINS_OP 118
|
||||
|
@ -81,8 +81,8 @@ extern "C" {
|
|||
#define LOAD_FAST 124
|
||||
#define STORE_FAST 125
|
||||
#define DELETE_FAST 126
|
||||
#define POP_JUMP_IF_NOT_NONE 128
|
||||
#define POP_JUMP_IF_NONE 129
|
||||
#define POP_JUMP_FORWARD_IF_NOT_NONE 128
|
||||
#define POP_JUMP_FORWARD_IF_NONE 129
|
||||
#define RAISE_VARARGS 130
|
||||
#define GET_AWAITABLE 131
|
||||
#define MAKE_FUNCTION 132
|
||||
|
@ -114,6 +114,10 @@ extern "C" {
|
|||
#define PRECALL 166
|
||||
#define CALL 171
|
||||
#define KW_NAMES 172
|
||||
#define POP_JUMP_BACKWARD_IF_NOT_NONE 173
|
||||
#define POP_JUMP_BACKWARD_IF_NONE 174
|
||||
#define POP_JUMP_BACKWARD_IF_FALSE 175
|
||||
#define POP_JUMP_BACKWARD_IF_TRUE 176
|
||||
#define BINARY_OP_ADAPTIVE 3
|
||||
#define BINARY_OP_ADD_FLOAT 4
|
||||
#define BINARY_OP_ADD_INT 5
|
||||
|
@ -181,9 +185,9 @@ extern "C" {
|
|||
#define STORE_SUBSCR_DICT 168
|
||||
#define STORE_SUBSCR_LIST_INT 169
|
||||
#define UNPACK_SEQUENCE_ADAPTIVE 170
|
||||
#define UNPACK_SEQUENCE_LIST 173
|
||||
#define UNPACK_SEQUENCE_TUPLE 174
|
||||
#define UNPACK_SEQUENCE_TWO_TUPLE 175
|
||||
#define UNPACK_SEQUENCE_LIST 177
|
||||
#define UNPACK_SEQUENCE_TUPLE 178
|
||||
#define UNPACK_SEQUENCE_TWO_TUPLE 179
|
||||
#define DO_TRACING 255
|
||||
|
||||
extern const uint8_t _PyOpcode_Caches[256];
|
||||
|
@ -195,9 +199,9 @@ static const uint32_t _PyOpcode_RelativeJump[8] = {
|
|||
0U,
|
||||
0U,
|
||||
536870912U,
|
||||
134234112U,
|
||||
4160U,
|
||||
0U,
|
||||
135020544U,
|
||||
4163U,
|
||||
122880U,
|
||||
0U,
|
||||
0U,
|
||||
};
|
||||
|
@ -207,7 +211,7 @@ static const uint32_t _PyOpcode_Jump[8] = {
|
|||
536870912U,
|
||||
135118848U,
|
||||
4163U,
|
||||
0U,
|
||||
122880U,
|
||||
0U,
|
||||
0U,
|
||||
};
|
||||
|
@ -338,10 +342,14 @@ const uint8_t _PyOpcode_Deopt[256] = {
|
|||
[MATCH_SEQUENCE] = MATCH_SEQUENCE,
|
||||
[NOP] = NOP,
|
||||
[POP_EXCEPT] = POP_EXCEPT,
|
||||
[POP_JUMP_IF_FALSE] = POP_JUMP_IF_FALSE,
|
||||
[POP_JUMP_IF_NONE] = POP_JUMP_IF_NONE,
|
||||
[POP_JUMP_IF_NOT_NONE] = POP_JUMP_IF_NOT_NONE,
|
||||
[POP_JUMP_IF_TRUE] = POP_JUMP_IF_TRUE,
|
||||
[POP_JUMP_BACKWARD_IF_FALSE] = POP_JUMP_BACKWARD_IF_FALSE,
|
||||
[POP_JUMP_BACKWARD_IF_NONE] = POP_JUMP_BACKWARD_IF_NONE,
|
||||
[POP_JUMP_BACKWARD_IF_NOT_NONE] = POP_JUMP_BACKWARD_IF_NOT_NONE,
|
||||
[POP_JUMP_BACKWARD_IF_TRUE] = POP_JUMP_BACKWARD_IF_TRUE,
|
||||
[POP_JUMP_FORWARD_IF_FALSE] = POP_JUMP_FORWARD_IF_FALSE,
|
||||
[POP_JUMP_FORWARD_IF_NONE] = POP_JUMP_FORWARD_IF_NONE,
|
||||
[POP_JUMP_FORWARD_IF_NOT_NONE] = POP_JUMP_FORWARD_IF_NOT_NONE,
|
||||
[POP_JUMP_FORWARD_IF_TRUE] = POP_JUMP_FORWARD_IF_TRUE,
|
||||
[POP_TOP] = POP_TOP,
|
||||
[PRECALL] = PRECALL,
|
||||
[PRECALL_ADAPTIVE] = PRECALL,
|
||||
|
|
|
@ -392,6 +392,9 @@ def parse_exception_table(code):
|
|||
except StopIteration:
|
||||
return entries
|
||||
|
||||
def _is_backward_jump(op):
|
||||
return 'JUMP_BACKWARD' in opname[op]
|
||||
|
||||
def _get_instructions_bytes(code, varname_from_oparg=None,
|
||||
names=None, co_consts=None,
|
||||
linestarts=None, line_offset=0,
|
||||
|
@ -442,7 +445,7 @@ def _get_instructions_bytes(code, varname_from_oparg=None,
|
|||
argval = arg*2
|
||||
argrepr = "to " + repr(argval)
|
||||
elif op in hasjrel:
|
||||
signed_arg = -arg if op == JUMP_BACKWARD else arg
|
||||
signed_arg = -arg if _is_backward_jump(op) else arg
|
||||
argval = offset + 2 + signed_arg*2
|
||||
argrepr = "to " + repr(argval)
|
||||
elif op in haslocal or op in hasfree:
|
||||
|
@ -568,7 +571,7 @@ def findlabels(code):
|
|||
for offset, op, arg in _unpack_opargs(code):
|
||||
if arg is not None:
|
||||
if op in hasjrel:
|
||||
if op == JUMP_BACKWARD:
|
||||
if _is_backward_jump(op):
|
||||
arg = -arg
|
||||
label = offset + 2 + arg*2
|
||||
elif op in hasjabs:
|
||||
|
|
|
@ -400,6 +400,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Python 3.11a6 3490 (remove JUMP_IF_NOT_EXC_MATCH, add CHECK_EXC_MATCH)
|
||||
# Python 3.11a6 3491 (remove JUMP_IF_NOT_EG_MATCH, add CHECK_EG_MATCH,
|
||||
# add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual)
|
||||
# Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative)
|
||||
|
||||
# Python 3.12 will start with magic number 3500
|
||||
|
||||
|
@ -414,7 +415,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 = (3491).to_bytes(2, 'little') + b'\r\n'
|
||||
MAGIC_NUMBER = (3492).to_bytes(2, 'little') + b'\r\n'
|
||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||
|
||||
_PYCACHE = '__pycache__'
|
||||
|
|
|
@ -133,8 +133,8 @@ name_op('IMPORT_FROM', 109) # Index in name list
|
|||
jrel_op('JUMP_FORWARD', 110) # Number of words to skip
|
||||
jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
|
||||
jabs_op('JUMP_IF_TRUE_OR_POP', 112) # ""
|
||||
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
|
||||
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
|
||||
jrel_op('POP_JUMP_FORWARD_IF_FALSE', 114)
|
||||
jrel_op('POP_JUMP_FORWARD_IF_TRUE', 115)
|
||||
name_op('LOAD_GLOBAL', 116, 5) # Index in name list
|
||||
def_op('IS_OP', 117)
|
||||
def_op('CONTAINS_OP', 118)
|
||||
|
@ -148,8 +148,8 @@ def_op('STORE_FAST', 125) # Local variable number
|
|||
haslocal.append(125)
|
||||
def_op('DELETE_FAST', 126) # Local variable number
|
||||
haslocal.append(126)
|
||||
jabs_op('POP_JUMP_IF_NOT_NONE', 128)
|
||||
jabs_op('POP_JUMP_IF_NONE', 129)
|
||||
jrel_op('POP_JUMP_FORWARD_IF_NOT_NONE', 128)
|
||||
jrel_op('POP_JUMP_FORWARD_IF_NONE', 129)
|
||||
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
|
||||
def_op('GET_AWAITABLE', 131)
|
||||
def_op('MAKE_FUNCTION', 132) # Flags
|
||||
|
@ -197,6 +197,11 @@ def_op('CALL', 171, 4)
|
|||
def_op('KW_NAMES', 172)
|
||||
hasconst.append(172)
|
||||
|
||||
jrel_op('POP_JUMP_BACKWARD_IF_NOT_NONE', 173)
|
||||
jrel_op('POP_JUMP_BACKWARD_IF_NONE', 174)
|
||||
jrel_op('POP_JUMP_BACKWARD_IF_FALSE', 175)
|
||||
jrel_op('POP_JUMP_BACKWARD_IF_TRUE', 176)
|
||||
|
||||
|
||||
del def_op, name_op, jrel_op, jabs_op
|
||||
|
||||
|
|
|
@ -373,7 +373,7 @@ dis_traceback = """\
|
|||
|
||||
%3d LOAD_GLOBAL 0 (Exception)
|
||||
CHECK_EXC_MATCH
|
||||
POP_JUMP_IF_FALSE 36 (to 72)
|
||||
POP_JUMP_FORWARD_IF_FALSE 18 (to 72)
|
||||
STORE_FAST 0 (e)
|
||||
|
||||
%3d LOAD_FAST 0 (e)
|
||||
|
@ -685,7 +685,15 @@ class DisTests(DisTestBase):
|
|||
for opcode, opname in enumerate(dis.opname):
|
||||
if opname in ('BUILD_MAP_UNPACK_WITH_CALL',
|
||||
'BUILD_TUPLE_UNPACK_WITH_CALL',
|
||||
'JUMP_BACKWARD_NO_INTERRUPT'):
|
||||
'JUMP_BACKWARD_NO_INTERRUPT',
|
||||
'POP_JUMP_FORWARD_IF_NONE',
|
||||
'POP_JUMP_BACKWARD_IF_NONE',
|
||||
'POP_JUMP_FORWARD_IF_NOT_NONE',
|
||||
'POP_JUMP_BACKWARD_IF_NOT_NONE',
|
||||
'POP_JUMP_FORWARD_IF_TRUE',
|
||||
'POP_JUMP_BACKWARD_IF_TRUE',
|
||||
'POP_JUMP_FORWARD_IF_FALSE',
|
||||
'POP_JUMP_BACKWARD_IF_FALSE'):
|
||||
continue
|
||||
with self.subTest(opname=opname):
|
||||
width = dis._OPNAME_WIDTH
|
||||
|
@ -1227,12 +1235,12 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=5, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=68, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=70, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=40, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=80, argrepr='to 80', offset=76, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=32, argrepr='to 32', offset=78, starts_line=6, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=80, starts_line=7, is_jump_target=True, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=82, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=84, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=48, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=2, argval=96, argrepr='to 96', offset=90, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=92, starts_line=8, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=16, argval=128, argrepr='to 128', offset=94, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=33, argval=32, argrepr='to 32', offset=96, starts_line=7, is_jump_target=True, positions=None),
|
||||
|
@ -1242,7 +1250,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=128, starts_line=11, is_jump_target=True, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=102, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=36, argval=204, argrepr='to 204', offset=130, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=132, starts_line=12, is_jump_target=True, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1255,15 +1263,15 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=14, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=174, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=176, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=93, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=186, argrepr='to 186', offset=182, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=29, argval=128, argrepr='to 128', offset=184, starts_line=15, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=16, is_jump_target=True, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=188, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=190, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=100, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=200, argrepr='to 200', offset=196, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=234, argrepr='to 234', offset=198, starts_line=17, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=200, starts_line=11, is_jump_target=True, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=66, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=36, argval=132, argrepr='to 132', offset=202, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=204, starts_line=19, is_jump_target=True, positions=None),
|
||||
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=216, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1291,7 +1299,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=328, argrepr='to 328', offset=304, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=160, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_TRUE', opcode=115, arg=4, argval=320, argrepr='to 320', offset=310, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=314, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
@ -1304,7 +1312,7 @@ expected_opinfo_jumpy = [
|
|||
Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=332, starts_line=22, is_jump_target=False, positions=None),
|
||||
Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=192, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=18, argval=384, argrepr='to 384', offset=346, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=350, starts_line=23, is_jump_target=False, positions=None),
|
||||
Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=362, starts_line=None, is_jump_target=False, positions=None),
|
||||
|
|
|
@ -76,8 +76,9 @@ class TestTranforms(BytecodeTestCase):
|
|||
if not x == 2:
|
||||
del x
|
||||
self.assertNotInBytecode(unot, 'UNARY_NOT')
|
||||
self.assertNotInBytecode(unot, 'POP_JUMP_IF_FALSE')
|
||||
self.assertInBytecode(unot, 'POP_JUMP_IF_TRUE')
|
||||
self.assertNotInBytecode(unot, 'POP_JUMP_FORWARD_IF_FALSE')
|
||||
self.assertNotInBytecode(unot, 'POP_JUMP_BACKWARD_IF_FALSE')
|
||||
self.assertInBytecode(unot, 'POP_JUMP_FORWARD_IF_TRUE')
|
||||
self.check_lnotab(unot)
|
||||
|
||||
def test_elim_inversion_of_is_or_in(self):
|
||||
|
@ -405,7 +406,7 @@ class TestTranforms(BytecodeTestCase):
|
|||
self.check_lnotab(f)
|
||||
self.assertNotInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
|
||||
self.assertInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
|
||||
self.assertInBytecode(f, 'POP_JUMP_IF_FALSE')
|
||||
self.assertInBytecode(f, 'POP_JUMP_FORWARD_IF_FALSE')
|
||||
# JUMP_IF_TRUE_OR_POP to JUMP_IF_FALSE_OR_POP --> POP_JUMP_IF_TRUE to non-jump
|
||||
def f(a, b, c):
|
||||
return ((a or b)
|
||||
|
@ -414,7 +415,7 @@ class TestTranforms(BytecodeTestCase):
|
|||
self.check_lnotab(f)
|
||||
self.assertNotInBytecode(f, 'JUMP_IF_TRUE_OR_POP')
|
||||
self.assertInBytecode(f, 'JUMP_IF_FALSE_OR_POP')
|
||||
self.assertInBytecode(f, 'POP_JUMP_IF_TRUE')
|
||||
self.assertInBytecode(f, 'POP_JUMP_FORWARD_IF_TRUE')
|
||||
|
||||
def test_elim_jump_after_return1(self):
|
||||
# Eliminate dead code: jumps immediately after returns can't be reached
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Make :opcode:`POP_JUMP_IF_TRUE`, :opcode:`POP_JUMP_IF_FALSE`, :opcode:`POP_JUMP_IF_NONE` and :opcode:`POP_JUMP_IF_NOT_NONE` virtual, mapping to new relative jump opcodes.
|
|
@ -206,11 +206,21 @@ mark_stacks(PyCodeObject *code_obj, int len)
|
|||
switch (opcode) {
|
||||
case JUMP_IF_FALSE_OR_POP:
|
||||
case JUMP_IF_TRUE_OR_POP:
|
||||
case POP_JUMP_IF_FALSE:
|
||||
case POP_JUMP_IF_TRUE:
|
||||
case POP_JUMP_FORWARD_IF_FALSE:
|
||||
case POP_JUMP_BACKWARD_IF_FALSE:
|
||||
case POP_JUMP_FORWARD_IF_TRUE:
|
||||
case POP_JUMP_BACKWARD_IF_TRUE:
|
||||
{
|
||||
int64_t target_stack;
|
||||
int j = get_arg(code, i);
|
||||
if (opcode == POP_JUMP_FORWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_TRUE) {
|
||||
j += i + 1;
|
||||
}
|
||||
else if (opcode == POP_JUMP_BACKWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_TRUE) {
|
||||
j = i + 1 - j;
|
||||
}
|
||||
assert(j < len);
|
||||
if (stacks[j] == UNINITIALIZED && j < i) {
|
||||
todo = 1;
|
||||
|
|
179
Python/ceval.c
179
Python/ceval.c
|
@ -3646,8 +3646,6 @@ handle_eval_breaker:
|
|||
goto error;
|
||||
}
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
|
||||
PREDICT(POP_JUMP_IF_FALSE);
|
||||
PREDICT(POP_JUMP_IF_TRUE);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -3670,7 +3668,7 @@ handle_eval_breaker:
|
|||
|
||||
TARGET(COMPARE_OP_FLOAT_JUMP) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
// Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
|
||||
// Combined: COMPARE_OP (float ? float) + POP_JUMP_(direction)_IF_(true/false)
|
||||
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
|
||||
int when_to_jump_mask = cache->mask;
|
||||
PyObject *right = TOP();
|
||||
|
@ -3688,22 +3686,31 @@ handle_eval_breaker:
|
|||
STACK_SHRINK(2);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
|
||||
int jump = (1 << (sign + 1)) & when_to_jump_mask;
|
||||
assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_TRUE);
|
||||
int jump = (9 << (sign + 1)) & when_to_jump_mask;
|
||||
if (!jump) {
|
||||
next_instr++;
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
else if (jump >= 8) {
|
||||
assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_FALSE);
|
||||
JUMPBY(1 - oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
else {
|
||||
JUMPTO(oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
NOTRACE_DISPATCH();
|
||||
assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_FALSE);
|
||||
JUMPBY(1 + oparg);
|
||||
}
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(COMPARE_OP_INT_JUMP) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
// Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false)
|
||||
// Combined: COMPARE_OP (int ? int) + POP_JUMP_(direction)_IF_(true/false)
|
||||
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
|
||||
int when_to_jump_mask = cache->mask;
|
||||
PyObject *right = TOP();
|
||||
|
@ -3722,24 +3729,33 @@ handle_eval_breaker:
|
|||
STACK_SHRINK(2);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
|
||||
int jump = (1 << (sign + 1)) & when_to_jump_mask;
|
||||
assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_TRUE);
|
||||
int jump = (9 << (sign + 1)) & when_to_jump_mask;
|
||||
if (!jump) {
|
||||
next_instr++;
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
else if (jump >= 8) {
|
||||
assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_FALSE);
|
||||
JUMPBY(1 - oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
else {
|
||||
JUMPTO(oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
NOTRACE_DISPATCH();
|
||||
assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_FALSE);
|
||||
JUMPBY(1 + oparg);
|
||||
}
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(COMPARE_OP_STR_JUMP) {
|
||||
assert(cframe.use_tracing == 0);
|
||||
// Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false)
|
||||
// Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_(direction)_IF_(true/false)
|
||||
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
|
||||
int invert = cache->mask;
|
||||
int when_to_jump_mask = cache->mask;
|
||||
PyObject *right = TOP();
|
||||
PyObject *left = SECOND();
|
||||
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
|
||||
|
@ -3752,22 +3768,31 @@ handle_eval_breaker:
|
|||
assert(oparg == Py_EQ || oparg == Py_NE);
|
||||
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
|
||||
NEXTOPARG();
|
||||
assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
|
||||
assert(opcode == POP_JUMP_FORWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_FALSE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_TRUE);
|
||||
STACK_SHRINK(2);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
assert(res == 0 || res == 1);
|
||||
assert(invert == 0 || invert == 1);
|
||||
int jump = res ^ invert;
|
||||
int sign = 1 - res;
|
||||
int jump = (9 << (sign + 1)) & when_to_jump_mask;
|
||||
if (!jump) {
|
||||
next_instr++;
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
else if (jump >= 8) {
|
||||
assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_BACKWARD_IF_FALSE);
|
||||
JUMPBY(1 - oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
else {
|
||||
JUMPTO(oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
NOTRACE_DISPATCH();
|
||||
assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
|
||||
opcode == POP_JUMP_FORWARD_IF_FALSE);
|
||||
JUMPBY(1 + oparg);
|
||||
}
|
||||
NOTRACE_DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(IS_OP) {
|
||||
|
@ -3779,8 +3804,6 @@ handle_eval_breaker:
|
|||
SET_TOP(b);
|
||||
Py_DECREF(left);
|
||||
Py_DECREF(right);
|
||||
PREDICT(POP_JUMP_IF_FALSE);
|
||||
PREDICT(POP_JUMP_IF_TRUE);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -3796,8 +3819,6 @@ handle_eval_breaker:
|
|||
PyObject *b = (res^oparg) ? Py_True : Py_False;
|
||||
Py_INCREF(b);
|
||||
PUSH(b);
|
||||
PREDICT(POP_JUMP_IF_FALSE);
|
||||
PREDICT(POP_JUMP_IF_TRUE);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -3915,26 +3936,25 @@ handle_eval_breaker:
|
|||
JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK);
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_IF_FALSE) {
|
||||
PREDICTED(POP_JUMP_IF_FALSE);
|
||||
TARGET(POP_JUMP_BACKWARD_IF_FALSE) {
|
||||
PREDICTED(POP_JUMP_BACKWARD_IF_FALSE);
|
||||
PyObject *cond = POP();
|
||||
int err;
|
||||
if (Py_IsTrue(cond)) {
|
||||
Py_DECREF(cond);
|
||||
DISPATCH();
|
||||
}
|
||||
if (Py_IsFalse(cond)) {
|
||||
Py_DECREF(cond);
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(-oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
DISPATCH();
|
||||
}
|
||||
err = PyObject_IsTrue(cond);
|
||||
int err = PyObject_IsTrue(cond);
|
||||
Py_DECREF(cond);
|
||||
if (err > 0)
|
||||
;
|
||||
else if (err == 0) {
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(-oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
else
|
||||
|
@ -3942,24 +3962,46 @@ handle_eval_breaker:
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_IF_TRUE) {
|
||||
PREDICTED(POP_JUMP_IF_TRUE);
|
||||
TARGET(POP_JUMP_FORWARD_IF_FALSE) {
|
||||
PREDICTED(POP_JUMP_FORWARD_IF_FALSE);
|
||||
PyObject *cond = POP();
|
||||
if (Py_IsTrue(cond)) {
|
||||
Py_DECREF(cond);
|
||||
}
|
||||
else if (Py_IsFalse(cond)) {
|
||||
Py_DECREF(cond);
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else {
|
||||
int err = PyObject_IsTrue(cond);
|
||||
Py_DECREF(cond);
|
||||
if (err > 0)
|
||||
;
|
||||
else if (err == 0) {
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_BACKWARD_IF_TRUE) {
|
||||
PyObject *cond = POP();
|
||||
int err;
|
||||
if (Py_IsFalse(cond)) {
|
||||
Py_DECREF(cond);
|
||||
DISPATCH();
|
||||
}
|
||||
if (Py_IsTrue(cond)) {
|
||||
Py_DECREF(cond);
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(-oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
DISPATCH();
|
||||
}
|
||||
err = PyObject_IsTrue(cond);
|
||||
int err = PyObject_IsTrue(cond);
|
||||
Py_DECREF(cond);
|
||||
if (err > 0) {
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(-oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
}
|
||||
else if (err == 0)
|
||||
|
@ -3969,11 +4011,34 @@ handle_eval_breaker:
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_IF_NOT_NONE) {
|
||||
TARGET(POP_JUMP_FORWARD_IF_TRUE) {
|
||||
PyObject *cond = POP();
|
||||
if (Py_IsFalse(cond)) {
|
||||
Py_DECREF(cond);
|
||||
}
|
||||
else if (Py_IsTrue(cond)) {
|
||||
Py_DECREF(cond);
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else {
|
||||
int err = PyObject_IsTrue(cond);
|
||||
Py_DECREF(cond);
|
||||
if (err > 0) {
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
else if (err == 0)
|
||||
;
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_BACKWARD_IF_NOT_NONE) {
|
||||
PyObject *value = POP();
|
||||
if (!Py_IsNone(value)) {
|
||||
Py_DECREF(value);
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(-oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -3981,11 +4046,20 @@ handle_eval_breaker:
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_IF_NONE) {
|
||||
TARGET(POP_JUMP_FORWARD_IF_NOT_NONE) {
|
||||
PyObject *value = POP();
|
||||
if (!Py_IsNone(value)) {
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
Py_DECREF(value);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_BACKWARD_IF_NONE) {
|
||||
PyObject *value = POP();
|
||||
if (Py_IsNone(value)) {
|
||||
Py_DECREF(value);
|
||||
JUMPTO(oparg);
|
||||
JUMPBY(-oparg);
|
||||
CHECK_EVAL_BREAKER();
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -3993,6 +4067,15 @@ handle_eval_breaker:
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(POP_JUMP_FORWARD_IF_NONE) {
|
||||
PyObject *value = POP();
|
||||
if (Py_IsNone(value)) {
|
||||
JUMPBY(oparg);
|
||||
}
|
||||
Py_DECREF(value);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(JUMP_IF_FALSE_OR_POP) {
|
||||
PyObject *cond = TOP();
|
||||
int err;
|
||||
|
@ -4108,7 +4191,8 @@ handle_eval_breaker:
|
|||
PyObject *res = match ? Py_True : Py_False;
|
||||
Py_INCREF(res);
|
||||
PUSH(res);
|
||||
PREDICT(POP_JUMP_IF_FALSE);
|
||||
PREDICT(POP_JUMP_FORWARD_IF_FALSE);
|
||||
PREDICT(POP_JUMP_BACKWARD_IF_FALSE);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -4118,7 +4202,8 @@ handle_eval_breaker:
|
|||
PyObject *res = match ? Py_True : Py_False;
|
||||
Py_INCREF(res);
|
||||
PUSH(res);
|
||||
PREDICT(POP_JUMP_IF_FALSE);
|
||||
PREDICT(POP_JUMP_FORWARD_IF_FALSE);
|
||||
PREDICT(POP_JUMP_BACKWARD_IF_FALSE);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,12 @@
|
|||
#define POP_BLOCK -4
|
||||
#define JUMP -5
|
||||
#define JUMP_NO_INTERRUPT -6
|
||||
#define POP_JUMP_IF_FALSE -7
|
||||
#define POP_JUMP_IF_TRUE -8
|
||||
#define POP_JUMP_IF_NONE -9
|
||||
#define POP_JUMP_IF_NOT_NONE -10
|
||||
|
||||
#define MIN_VIRTUAL_OPCODE -6
|
||||
#define MIN_VIRTUAL_OPCODE -10
|
||||
#define MAX_ALLOWED_OPCODE 254
|
||||
|
||||
#define IS_WITHIN_OPCODE_RANGE(opcode) \
|
||||
|
@ -87,11 +91,36 @@
|
|||
|
||||
#define IS_VIRTUAL_OPCODE(opcode) ((opcode) < 0)
|
||||
|
||||
#define IS_VIRTUAL_JUMP_OPCODE(opcode) \
|
||||
((opcode) == JUMP || \
|
||||
(opcode) == JUMP_NO_INTERRUPT || \
|
||||
(opcode) == POP_JUMP_IF_NONE || \
|
||||
(opcode) == POP_JUMP_IF_NOT_NONE || \
|
||||
(opcode) == POP_JUMP_IF_FALSE || \
|
||||
(opcode) == POP_JUMP_IF_TRUE)
|
||||
|
||||
/* opcodes which are not emitted in codegen stage, only by the assembler */
|
||||
#define IS_ASSEMBLER_OPCODE(opcode) \
|
||||
((opcode) == JUMP_FORWARD || \
|
||||
(opcode) == JUMP_BACKWARD || \
|
||||
(opcode) == JUMP_BACKWARD_NO_INTERRUPT)
|
||||
(opcode) == JUMP_BACKWARD_NO_INTERRUPT || \
|
||||
(opcode) == POP_JUMP_FORWARD_IF_NONE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_NONE || \
|
||||
(opcode) == POP_JUMP_FORWARD_IF_NOT_NONE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \
|
||||
(opcode) == POP_JUMP_FORWARD_IF_TRUE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_TRUE || \
|
||||
(opcode) == POP_JUMP_FORWARD_IF_FALSE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_FALSE)
|
||||
|
||||
|
||||
#define IS_BACKWARDS_JUMP_OPCODE(opcode) \
|
||||
((opcode) == JUMP_BACKWARD || \
|
||||
(opcode) == JUMP_BACKWARD_NO_INTERRUPT || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_NONE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_NOT_NONE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_TRUE || \
|
||||
(opcode) == POP_JUMP_BACKWARD_IF_FALSE)
|
||||
|
||||
|
||||
#define IS_TOP_LEVEL_AWAIT(c) ( \
|
||||
|
@ -156,7 +185,7 @@ is_block_push(struct instr *instr)
|
|||
static inline int
|
||||
is_jump(struct instr *i)
|
||||
{
|
||||
return i->i_opcode == JUMP ||
|
||||
return IS_VIRTUAL_JUMP_OPCODE(i->i_opcode) ||
|
||||
is_bit_set_in_table(_PyOpcode_Jump, i->i_opcode);
|
||||
}
|
||||
|
||||
|
@ -1027,10 +1056,18 @@ stack_effect(int opcode, int oparg, int jump)
|
|||
case JUMP_IF_FALSE_OR_POP:
|
||||
return jump ? 0 : -1;
|
||||
|
||||
case POP_JUMP_IF_FALSE:
|
||||
case POP_JUMP_IF_TRUE:
|
||||
case POP_JUMP_BACKWARD_IF_NONE:
|
||||
case POP_JUMP_FORWARD_IF_NONE:
|
||||
case POP_JUMP_IF_NONE:
|
||||
case POP_JUMP_BACKWARD_IF_NOT_NONE:
|
||||
case POP_JUMP_FORWARD_IF_NOT_NONE:
|
||||
case POP_JUMP_IF_NOT_NONE:
|
||||
case POP_JUMP_FORWARD_IF_FALSE:
|
||||
case POP_JUMP_BACKWARD_IF_FALSE:
|
||||
case POP_JUMP_IF_FALSE:
|
||||
case POP_JUMP_FORWARD_IF_TRUE:
|
||||
case POP_JUMP_BACKWARD_IF_TRUE:
|
||||
case POP_JUMP_IF_TRUE:
|
||||
return -1;
|
||||
|
||||
case LOAD_GLOBAL:
|
||||
|
@ -7609,14 +7646,33 @@ normalize_jumps(struct assembler *a)
|
|||
}
|
||||
struct instr *last = &b->b_instr[b->b_iused-1];
|
||||
assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
|
||||
if (last->i_opcode == JUMP) {
|
||||
if (is_jump(last)) {
|
||||
bool is_forward = last->i_target->b_visited == 0;
|
||||
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
|
||||
}
|
||||
if (last->i_opcode == JUMP_NO_INTERRUPT) {
|
||||
bool is_forward = last->i_target->b_visited == 0;
|
||||
last->i_opcode = is_forward ?
|
||||
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
|
||||
switch(last->i_opcode) {
|
||||
case JUMP:
|
||||
last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
|
||||
break;
|
||||
case JUMP_NO_INTERRUPT:
|
||||
last->i_opcode = is_forward ?
|
||||
JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
|
||||
break;
|
||||
case POP_JUMP_IF_NOT_NONE:
|
||||
last->i_opcode = is_forward ?
|
||||
POP_JUMP_FORWARD_IF_NOT_NONE : POP_JUMP_BACKWARD_IF_NOT_NONE;
|
||||
break;
|
||||
case POP_JUMP_IF_NONE:
|
||||
last->i_opcode = is_forward ?
|
||||
POP_JUMP_FORWARD_IF_NONE : POP_JUMP_BACKWARD_IF_NONE;
|
||||
break;
|
||||
case POP_JUMP_IF_FALSE:
|
||||
last->i_opcode = is_forward ?
|
||||
POP_JUMP_FORWARD_IF_FALSE : POP_JUMP_BACKWARD_IF_FALSE;
|
||||
break;
|
||||
case POP_JUMP_IF_TRUE:
|
||||
last->i_opcode = is_forward ?
|
||||
POP_JUMP_FORWARD_IF_TRUE : POP_JUMP_BACKWARD_IF_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7652,16 +7708,17 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
|
|||
instr->i_oparg = instr->i_target->b_offset;
|
||||
if (is_relative_jump(instr)) {
|
||||
if (instr->i_oparg < bsize) {
|
||||
assert(instr->i_opcode == JUMP_BACKWARD ||
|
||||
instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT);
|
||||
assert(IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
|
||||
instr->i_oparg = bsize - instr->i_oparg;
|
||||
}
|
||||
else {
|
||||
assert(instr->i_opcode != JUMP_BACKWARD);
|
||||
assert(instr->i_opcode != JUMP_BACKWARD_NO_INTERRUPT);
|
||||
assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
|
||||
instr->i_oparg -= bsize;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(!IS_BACKWARDS_JUMP_OPCODE(instr->i_opcode));
|
||||
}
|
||||
if (instr_size(instr) != isize) {
|
||||
extended_arg_recompile = 1;
|
||||
}
|
||||
|
@ -8644,7 +8701,7 @@ apply_static_swaps(basicblock *block, int i)
|
|||
static bool
|
||||
jump_thread(struct instr *inst, struct instr *target, int opcode)
|
||||
{
|
||||
assert(!IS_VIRTUAL_OPCODE(opcode) || opcode == JUMP);
|
||||
assert(!IS_VIRTUAL_OPCODE(opcode) || IS_VIRTUAL_JUMP_OPCODE(opcode));
|
||||
assert(is_jump(inst));
|
||||
assert(is_jump(target));
|
||||
// bpo-45773: If inst->i_target == target->i_target, then nothing actually
|
||||
|
|
|
@ -113,8 +113,8 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_JUMP_IF_FALSE_OR_POP,
|
||||
&&TARGET_JUMP_IF_TRUE_OR_POP,
|
||||
&&TARGET_PRECALL_NO_KW_STR_1,
|
||||
&&TARGET_POP_JUMP_IF_FALSE,
|
||||
&&TARGET_POP_JUMP_IF_TRUE,
|
||||
&&TARGET_POP_JUMP_FORWARD_IF_FALSE,
|
||||
&&TARGET_POP_JUMP_FORWARD_IF_TRUE,
|
||||
&&TARGET_LOAD_GLOBAL,
|
||||
&&TARGET_IS_OP,
|
||||
&&TARGET_CONTAINS_OP,
|
||||
|
@ -127,8 +127,8 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_STORE_FAST,
|
||||
&&TARGET_DELETE_FAST,
|
||||
&&TARGET_PRECALL_NO_KW_TYPE_1,
|
||||
&&TARGET_POP_JUMP_IF_NOT_NONE,
|
||||
&&TARGET_POP_JUMP_IF_NONE,
|
||||
&&TARGET_POP_JUMP_FORWARD_IF_NOT_NONE,
|
||||
&&TARGET_POP_JUMP_FORWARD_IF_NONE,
|
||||
&&TARGET_RAISE_VARARGS,
|
||||
&&TARGET_GET_AWAITABLE,
|
||||
&&TARGET_MAKE_FUNCTION,
|
||||
|
@ -172,6 +172,10 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_UNPACK_SEQUENCE_ADAPTIVE,
|
||||
&&TARGET_CALL,
|
||||
&&TARGET_KW_NAMES,
|
||||
&&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE,
|
||||
&&TARGET_POP_JUMP_BACKWARD_IF_NONE,
|
||||
&&TARGET_POP_JUMP_BACKWARD_IF_FALSE,
|
||||
&&TARGET_POP_JUMP_BACKWARD_IF_TRUE,
|
||||
&&TARGET_UNPACK_SEQUENCE_LIST,
|
||||
&&TARGET_UNPACK_SEQUENCE_TUPLE,
|
||||
&&TARGET_UNPACK_SEQUENCE_TWO_TUPLE,
|
||||
|
@ -250,9 +254,5 @@ static void *opcode_targets[256] = {
|
|||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_DO_TRACING
|
||||
};
|
||||
|
|
|
@ -1883,7 +1883,10 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
|||
assert(_PyOpcode_Caches[COMPARE_OP] == INLINE_CACHE_ENTRIES_COMPARE_OP);
|
||||
_PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);
|
||||
int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]);
|
||||
if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) {
|
||||
if (next_opcode != POP_JUMP_FORWARD_IF_FALSE &&
|
||||
next_opcode != POP_JUMP_BACKWARD_IF_FALSE &&
|
||||
next_opcode != POP_JUMP_FORWARD_IF_TRUE &&
|
||||
next_opcode != POP_JUMP_BACKWARD_IF_TRUE) {
|
||||
// Can't ever combine, so don't don't bother being adaptive (unless
|
||||
// we're collecting stats, where it's more important to get accurate hit
|
||||
// counts for the unadaptive version and each of the different failure
|
||||
|
@ -1901,9 +1904,14 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
|||
}
|
||||
assert(oparg <= Py_GE);
|
||||
int when_to_jump_mask = compare_masks[oparg];
|
||||
if (next_opcode == POP_JUMP_IF_FALSE) {
|
||||
if (next_opcode == POP_JUMP_FORWARD_IF_FALSE ||
|
||||
next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
|
||||
when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask;
|
||||
}
|
||||
if (next_opcode == POP_JUMP_BACKWARD_IF_TRUE ||
|
||||
next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
|
||||
when_to_jump_mask <<= 3;
|
||||
}
|
||||
if (Py_TYPE(lhs) != Py_TYPE(rhs)) {
|
||||
SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
|
||||
goto failure;
|
||||
|
@ -1931,7 +1939,7 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
|
|||
}
|
||||
else {
|
||||
_Py_SET_OPCODE(*instr, COMPARE_OP_STR_JUMP);
|
||||
cache->mask = (when_to_jump_mask & 2) == 0;
|
||||
cache->mask = when_to_jump_mask;
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue