Python-checkins
Threads by month
- ----- 2024 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
September 2022
- 1 participants
- 396 discussions
01 Sep '22
https://github.com/python/cpython/commit/4c72517cada147b215cf30ff8dac70ea0f…
commit: 4c72517cada147b215cf30ff8dac70ea0f08f1e0
branch: main
author: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel(a)users.noreply.github.com>
date: 2022-09-01T21:36:47+01:00
summary:
gh-93554: Conditional jump opcodes only jump forward (GH-96318)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst
M Doc/library/dis.rst
M Include/internal/pycore_opcode.h
M Include/opcode.h
M Lib/importlib/_bootstrap_external.py
M Lib/opcode.py
M Lib/test/test_dis.py
M Lib/test/test_peepholer.py
M Objects/frameobject.c
M Python/ceval.c
M Python/compile.c
M Python/opcode_targets.h
M Python/specialize.c
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 691819fbca03..47e4bf600721 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -999,60 +999,48 @@ iterations of the loop.
.. versionadded:: 3.11
-.. opcode:: POP_JUMP_FORWARD_IF_TRUE (delta)
+.. opcode:: POP_JUMP_IF_TRUE (delta)
If TOS is true, increments the bytecode counter by *delta*. TOS is popped.
- .. versionadded:: 3.11
-
-
-.. opcode:: POP_JUMP_BACKWARD_IF_TRUE (delta)
-
- If TOS is true, decrements the bytecode counter by *delta*. TOS is popped.
-
- .. versionadded:: 3.11
+ .. versionchanged:: 3.11
+ The oparg is now a relative delta rather than an absolute target.
+ This opcode is a pseudo-instruction, replaced in final bytecode by
+ the directed versions (forward/backward).
+ .. versionchanged:: 3.12
+ This is no longer a pseudo-instruction.
-.. opcode:: POP_JUMP_FORWARD_IF_FALSE (delta)
+.. opcode:: POP_JUMP_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
+ .. versionchanged:: 3.11
+ The oparg is now a relative delta rather than an absolute target.
+ This opcode is a pseudo-instruction, replaced in final bytecode by
+ the directed versions (forward/backward).
+ .. versionchanged:: 3.12
+ This is no longer a pseudo-instruction.
-.. opcode:: POP_JUMP_FORWARD_IF_NOT_NONE (delta)
+.. opcode:: POP_JUMP_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
+ .. versionchanged:: 3.12
+ This is no longer a pseudo-instruction.
-.. opcode:: POP_JUMP_FORWARD_IF_NONE (delta)
+.. opcode:: POP_JUMP_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
+ .. versionchanged:: 3.12
+ This is no longer a pseudo-instruction.
.. opcode:: JUMP_IF_TRUE_OR_POP (delta)
@@ -1433,10 +1421,6 @@ but are replaced by real opcodes or removed before bytecode is generated.
.. opcode:: JUMP
.. opcode:: JUMP_NO_INTERRUPT
-.. opcode:: POP_JUMP_IF_FALSE
-.. opcode:: POP_JUMP_IF_TRUE
-.. opcode:: POP_JUMP_IF_NONE
-.. opcode:: POP_JUMP_IF_NOT_NONE
Undirected relative jump instructions which are replaced by their
directed (forward/backward) counterparts by the assembler.
diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h
index 587590172b56..15925511cc1f 100644
--- a/Include/internal/pycore_opcode.h
+++ b/Include/internal/pycore_opcode.h
@@ -23,10 +23,10 @@ static const uint32_t _PyOpcode_RelativeJump[9] = {
536870912U,
135118848U,
4163U,
- 122880U,
0U,
0U,
- 1008U,
+ 0U,
+ 48U,
};
static const uint32_t _PyOpcode_Jump[9] = {
0U,
@@ -34,10 +34,10 @@ static const uint32_t _PyOpcode_Jump[9] = {
536870912U,
135118848U,
4163U,
- 122880U,
0U,
0U,
- 1008U,
+ 0U,
+ 48U,
};
const uint8_t _PyOpcode_Caches[256] = {
@@ -187,14 +187,10 @@ const uint8_t _PyOpcode_Deopt[256] = {
[MATCH_SEQUENCE] = MATCH_SEQUENCE,
[NOP] = NOP,
[POP_EXCEPT] = POP_EXCEPT,
- [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_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_TOP] = POP_TOP,
[PREP_RERAISE_STAR] = PREP_RERAISE_STAR,
[PRINT_EXPR] = PRINT_EXPR,
@@ -243,7 +239,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
#endif // NEED_OPCODE_TABLES
#ifdef Py_DEBUG
-static const char *const _PyOpcode_OpName[267] = {
+static const char *const _PyOpcode_OpName[263] = {
[CACHE] = "CACHE",
[POP_TOP] = "POP_TOP",
[PUSH_NULL] = "PUSH_NULL",
@@ -358,8 +354,8 @@ static const char *const _PyOpcode_OpName[267] = {
[JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP",
[JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP",
[LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT",
- [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE",
- [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE",
+ [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE",
+ [POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE",
[LOAD_GLOBAL] = "LOAD_GLOBAL",
[IS_OP] = "IS_OP",
[CONTAINS_OP] = "CONTAINS_OP",
@@ -372,8 +368,8 @@ static const char *const _PyOpcode_OpName[267] = {
[STORE_FAST] = "STORE_FAST",
[DELETE_FAST] = "DELETE_FAST",
[LOAD_FAST_CHECK] = "LOAD_FAST_CHECK",
- [POP_JUMP_FORWARD_IF_NOT_NONE] = "POP_JUMP_FORWARD_IF_NOT_NONE",
- [POP_JUMP_FORWARD_IF_NONE] = "POP_JUMP_FORWARD_IF_NONE",
+ [POP_JUMP_IF_NOT_NONE] = "POP_JUMP_IF_NOT_NONE",
+ [POP_JUMP_IF_NONE] = "POP_JUMP_IF_NONE",
[RAISE_VARARGS] = "RAISE_VARARGS",
[GET_AWAITABLE] = "GET_AWAITABLE",
[MAKE_FUNCTION] = "MAKE_FUNCTION",
@@ -417,10 +413,6 @@ static const char *const _PyOpcode_OpName[267] = {
[STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST",
[CALL] = "CALL",
[KW_NAMES] = "KW_NAMES",
- [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE",
- [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE",
- [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE",
- [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE",
[STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST",
[STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE",
[STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT",
@@ -429,6 +421,10 @@ static const char *const _PyOpcode_OpName[267] = {
[UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST",
[UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE",
[UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE",
+ [181] = "<181>",
+ [182] = "<182>",
+ [183] = "<183>",
+ [184] = "<184>",
[185] = "<185>",
[186] = "<186>",
[187] = "<187>",
@@ -506,15 +502,15 @@ static const char *const _PyOpcode_OpName[267] = {
[POP_BLOCK] = "POP_BLOCK",
[JUMP] = "JUMP",
[JUMP_NO_INTERRUPT] = "JUMP_NO_INTERRUPT",
- [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE",
- [POP_JUMP_IF_TRUE] = "POP_JUMP_IF_TRUE",
- [POP_JUMP_IF_NONE] = "POP_JUMP_IF_NONE",
- [POP_JUMP_IF_NOT_NONE] = "POP_JUMP_IF_NOT_NONE",
[LOAD_METHOD] = "LOAD_METHOD",
};
#endif
#define EXTRA_CASES \
+ case 181: \
+ case 182: \
+ case 183: \
+ case 184: \
case 185: \
case 186: \
case 187: \
diff --git a/Include/opcode.h b/Include/opcode.h
index cf11e5560674..42825df6217b 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -72,8 +72,8 @@ extern "C" {
#define JUMP_FORWARD 110
#define JUMP_IF_FALSE_OR_POP 111
#define JUMP_IF_TRUE_OR_POP 112
-#define POP_JUMP_FORWARD_IF_FALSE 114
-#define POP_JUMP_FORWARD_IF_TRUE 115
+#define POP_JUMP_IF_FALSE 114
+#define POP_JUMP_IF_TRUE 115
#define LOAD_GLOBAL 116
#define IS_OP 117
#define CONTAINS_OP 118
@@ -85,8 +85,8 @@ extern "C" {
#define STORE_FAST 125
#define DELETE_FAST 126
#define LOAD_FAST_CHECK 127
-#define POP_JUMP_FORWARD_IF_NOT_NONE 128
-#define POP_JUMP_FORWARD_IF_NONE 129
+#define POP_JUMP_IF_NOT_NONE 128
+#define POP_JUMP_IF_NONE 129
#define RAISE_VARARGS 130
#define GET_AWAITABLE 131
#define MAKE_FUNCTION 132
@@ -117,10 +117,6 @@ extern "C" {
#define DICT_UPDATE 165
#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 MIN_PSEUDO_OPCODE 256
#define SETUP_FINALLY 256
#define SETUP_CLEANUP 257
@@ -128,12 +124,8 @@ extern "C" {
#define POP_BLOCK 259
#define JUMP 260
#define JUMP_NO_INTERRUPT 261
-#define POP_JUMP_IF_FALSE 262
-#define POP_JUMP_IF_TRUE 263
-#define POP_JUMP_IF_NONE 264
-#define POP_JUMP_IF_NOT_NONE 265
-#define LOAD_METHOD 266
-#define MAX_PSEUDO_OPCODE 266
+#define LOAD_METHOD 262
+#define MAX_PSEUDO_OPCODE 262
#define BINARY_OP_ADAPTIVE 3
#define BINARY_OP_ADD_FLOAT 4
#define BINARY_OP_ADD_INT 5
@@ -199,23 +191,19 @@ extern "C" {
#define STORE_ATTR_SLOT 168
#define STORE_ATTR_WITH_HINT 169
#define STORE_FAST__LOAD_FAST 170
-#define STORE_FAST__STORE_FAST 177
-#define STORE_SUBSCR_ADAPTIVE 178
-#define STORE_SUBSCR_DICT 179
-#define STORE_SUBSCR_LIST_INT 180
-#define UNPACK_SEQUENCE_ADAPTIVE 181
-#define UNPACK_SEQUENCE_LIST 182
-#define UNPACK_SEQUENCE_TUPLE 183
-#define UNPACK_SEQUENCE_TWO_TUPLE 184
+#define STORE_FAST__STORE_FAST 173
+#define STORE_SUBSCR_ADAPTIVE 174
+#define STORE_SUBSCR_DICT 175
+#define STORE_SUBSCR_LIST_INT 176
+#define UNPACK_SEQUENCE_ADAPTIVE 177
+#define UNPACK_SEQUENCE_LIST 178
+#define UNPACK_SEQUENCE_TUPLE 179
+#define UNPACK_SEQUENCE_TWO_TUPLE 180
#define DO_TRACING 255
#define HAS_ARG(op) ((((op) >= HAVE_ARGUMENT) && (!IS_PSEUDO_OPCODE(op)))\
|| ((op) == JUMP) \
|| ((op) == JUMP_NO_INTERRUPT) \
- || ((op) == POP_JUMP_IF_FALSE) \
- || ((op) == POP_JUMP_IF_TRUE) \
- || ((op) == POP_JUMP_IF_NONE) \
- || ((op) == POP_JUMP_IF_NOT_NONE) \
|| ((op) == LOAD_METHOD) \
)
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index b30d0896c849..b3c31b9659d8 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -412,6 +412,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a1 3506 (Add BINARY_SLICE and STORE_SLICE instructions)
# Python 3.12a1 3507 (Set lineno of module's RESUME to 0)
# Python 3.12a1 3508 (Add CLEANUP_THROW)
+# Python 3.12a1 3509 (Conditional jumps only jump forward)
# Python 3.13 will start with 3550
@@ -424,7 +425,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3508).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3509).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 52c1271868e3..690923061418 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -153,8 +153,8 @@ def pseudo_op(name, op, real_ops):
jrel_op('JUMP_FORWARD', 110) # Number of words to skip
jrel_op('JUMP_IF_FALSE_OR_POP', 111) # Number of words to skip
jrel_op('JUMP_IF_TRUE_OR_POP', 112) # ""
-jrel_op('POP_JUMP_FORWARD_IF_FALSE', 114)
-jrel_op('POP_JUMP_FORWARD_IF_TRUE', 115)
+jrel_op('POP_JUMP_IF_FALSE', 114)
+jrel_op('POP_JUMP_IF_TRUE', 115)
name_op('LOAD_GLOBAL', 116) # Index in name list
def_op('IS_OP', 117)
def_op('CONTAINS_OP', 118)
@@ -170,8 +170,8 @@ def pseudo_op(name, op, real_ops):
haslocal.append(126)
def_op('LOAD_FAST_CHECK', 127) # Local variable number
haslocal.append(127)
-jrel_op('POP_JUMP_FORWARD_IF_NOT_NONE', 128)
-jrel_op('POP_JUMP_FORWARD_IF_NONE', 129)
+jrel_op('POP_JUMP_IF_NOT_NONE', 128)
+jrel_op('POP_JUMP_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
@@ -216,10 +216,6 @@ def pseudo_op(name, op, real_ops):
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)
hasarg.extend([op for op in opmap.values() if op >= HAVE_ARGUMENT])
@@ -235,11 +231,8 @@ def pseudo_op(name, op, real_ops):
pseudo_op('JUMP', 260, ['JUMP_FORWARD', 'JUMP_BACKWARD'])
pseudo_op('JUMP_NO_INTERRUPT', 261, ['JUMP_FORWARD', 'JUMP_BACKWARD_NO_INTERRUPT'])
-pseudo_op('POP_JUMP_IF_FALSE', 262, ['POP_JUMP_FORWARD_IF_FALSE', 'POP_JUMP_BACKWARD_IF_FALSE'])
-pseudo_op('POP_JUMP_IF_TRUE', 263, ['POP_JUMP_FORWARD_IF_TRUE', 'POP_JUMP_BACKWARD_IF_TRUE'])
-pseudo_op('POP_JUMP_IF_NONE', 264, ['POP_JUMP_FORWARD_IF_NONE', 'POP_JUMP_BACKWARD_IF_NONE'])
-pseudo_op('POP_JUMP_IF_NOT_NONE', 265, ['POP_JUMP_FORWARD_IF_NOT_NONE', 'POP_JUMP_BACKWARD_IF_NOT_NONE'])
-pseudo_op('LOAD_METHOD', 266, ['LOAD_ATTR'])
+
+pseudo_op('LOAD_METHOD', 262, ['LOAD_ATTR'])
MAX_PSEUDO_OPCODE = MIN_PSEUDO_OPCODE + len(_pseudo_ops) - 1
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 67cb1502add9..48d596027870 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -366,7 +366,7 @@ def bug42562():
%3d LOAD_GLOBAL 0 (Exception)
CHECK_EXC_MATCH
- POP_JUMP_FORWARD_IF_FALSE 22 (to 80)
+ POP_JUMP_IF_FALSE 22 (to 80)
STORE_FAST 0 (e)
%3d LOAD_FAST 0 (e)
@@ -447,7 +447,7 @@ def _with(c):
%3d >> PUSH_EXC_INFO
WITH_EXCEPT_START
- POP_JUMP_FORWARD_IF_TRUE 1 (to 46)
+ POP_JUMP_IF_TRUE 1 (to 46)
RERAISE 2
>> POP_TOP
POP_EXCEPT
@@ -520,7 +520,7 @@ async def _asyncwith(c):
RESUME 3
JUMP_BACKWARD_NO_INTERRUPT 4 (to 82)
>> CLEANUP_THROW
- >> POP_JUMP_FORWARD_IF_TRUE 1 (to 96)
+ >> POP_JUMP_IF_TRUE 1 (to 96)
RERAISE 2
>> POP_TOP
POP_EXCEPT
@@ -874,15 +874,7 @@ def test_boundaries(self):
self.assertEqual(dis.opmap["STORE_NAME"], dis.HAVE_ARGUMENT)
def test_widths(self):
- long_opcodes = set(['POP_JUMP_FORWARD_IF_FALSE',
- 'POP_JUMP_FORWARD_IF_TRUE',
- 'POP_JUMP_FORWARD_IF_NOT_NONE',
- 'POP_JUMP_FORWARD_IF_NONE',
- 'POP_JUMP_BACKWARD_IF_FALSE',
- 'POP_JUMP_BACKWARD_IF_TRUE',
- 'POP_JUMP_BACKWARD_IF_NOT_NONE',
- 'POP_JUMP_BACKWARD_IF_NONE',
- 'JUMP_BACKWARD_NO_INTERRUPT',
+ long_opcodes = set(['JUMP_BACKWARD_NO_INTERRUPT',
])
for opcode, opname in enumerate(dis.opname):
if opname in long_opcodes:
@@ -1544,7 +1536,7 @@ def _prepare_test_cases():
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=14, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='FOR_ITER', opcode=93, arg=29, argval=90, argrepr='to 90', offset=28, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='FOR_ITER', opcode=93, arg=30, argval=92, argrepr='to 92', offset=28, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=32, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=34, starts_line=4, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=46, starts_line=None, is_jump_target=False, positions=None),
@@ -1553,103 +1545,105 @@ def _prepare_test_cases():
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=60, starts_line=5, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=62, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=64, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=74, argrepr='to 74', offset=70, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=74, argrepr='to 74', offset=70, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='JUMP_BACKWARD', opcode=140, arg=23, argval=28, argrepr='to 28', offset=72, starts_line=6, is_jump_target=False, positions=None),
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=7, is_jump_target=True, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=76, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=78, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_BACKWARD_IF_FALSE', opcode=175, arg=29, argval=28, argrepr='to 28', offset=84, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=86, starts_line=8, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=116, argrepr='to 116', offset=88, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=90, starts_line=10, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=102, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=104, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=116, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=34, argval=188, argrepr='to 188', offset=118, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=120, starts_line=12, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=132, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=13, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=148, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=150, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=154, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=156, starts_line=14, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=158, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=160, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=170, argrepr='to 170', offset=166, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=116, argrepr='to 116', offset=168, starts_line=15, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=170, starts_line=16, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=172, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=174, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_FORWARD_IF_FALSE', opcode=114, arg=1, argval=184, argrepr='to 184', offset=180, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=15, argval=214, argrepr='to 214', offset=182, starts_line=17, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=184, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_BACKWARD_IF_TRUE', opcode=176, arg=34, argval=120, argrepr='to 120', offset=186, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=188, 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=200, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=214, starts_line=20, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=216, starts_line=21, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=218, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=220, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=226, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=230, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=232, starts_line=26, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=244, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=246, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=258, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=260, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=262, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=264, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=274, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=276, starts_line=28, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=288, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=290, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=300, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=302, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', 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=25, 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_FORWARD_IF_TRUE', opcode=115, arg=1, argval=314, argrepr='to 314', 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=314, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=276, argrepr='to 276', offset=322, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None),
- 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_FORWARD_IF_FALSE', opcode=114, arg=16, argval=380, argrepr='to 380', 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),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=364, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=374, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=376, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=276, argrepr='to 276', offset=378, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=380, starts_line=22, is_jump_target=True, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=390, starts_line=28, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=402, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=404, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=414, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=416, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=422, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=88, argrepr='to 88', offset=84, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=30, argval=28, argrepr='to 28', offset=86, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=88, starts_line=8, is_jump_target=True, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=118, argrepr='to 118', offset=90, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=92, starts_line=10, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=104, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=106, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST_CHECK', opcode=127, arg=0, argval='i', argrepr='i', offset=118, starts_line=11, is_jump_target=True, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=35, argval=192, argrepr='to 192', offset=120, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=122, starts_line=12, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=134, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=148, starts_line=13, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=150, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=152, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=156, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=158, starts_line=14, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=160, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=162, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=172, argrepr='to 172', offset=168, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=27, argval=118, argrepr='to 118', offset=170, starts_line=15, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=172, starts_line=16, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=174, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=176, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_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_FORWARD', opcode=110, arg=16, argval=218, argrepr='to 218', offset=184, starts_line=17, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=186, starts_line=11, is_jump_target=True, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=1, argval=192, argrepr='to 192', offset=188, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=35, argval=122, argrepr='to 122', offset=190, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=192, 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=204, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=218, starts_line=20, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=220, starts_line=21, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=222, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=224, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=230, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=234, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=236, starts_line=26, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=248, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=260, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=262, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=264, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=266, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=278, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=280, starts_line=28, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=292, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=294, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=306, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=310, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=1, argval=318, argrepr='to 318', offset=314, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=316, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=318, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=24, argval=280, argrepr='to 280', offset=326, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=330, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=332, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=334, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=336, starts_line=22, is_jump_target=False, positions=None),
+ Instruction(opname='CHECK_EXC_MATCH', opcode=36, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=16, argval=384, argrepr='to 384', offset=350, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=352, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=354, 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=366, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=368, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_BACKWARD', opcode=140, arg=52, argval=280, argrepr='to 280', offset=382, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=384, starts_line=22, is_jump_target=True, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=392, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=3, argval='print', argrepr='NULL + print', offset=394, starts_line=28, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=406, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=408, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=418, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=420, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=422, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=424, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=426, starts_line=None, is_jump_target=False, positions=None),
]
# One last piece of inspect fodder to check the default line number handling
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py
index 7cd9b060f5e9..5f7e50d4e757 100644
--- a/Lib/test/test_peepholer.py
+++ b/Lib/test/test_peepholer.py
@@ -77,9 +77,8 @@ def unot(x):
if not x == 2:
del x
self.assertNotInBytecode(unot, 'UNARY_NOT')
- 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.assertNotInBytecode(unot, 'POP_JUMP_IF_FALSE')
+ self.assertInBytecode(unot, 'POP_JUMP_IF_TRUE')
self.check_lnotab(unot)
def test_elim_inversion_of_is_or_in(self):
@@ -409,7 +408,7 @@ def f(a, b, c):
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_FORWARD_IF_FALSE')
+ self.assertInBytecode(f, 'POP_JUMP_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)
@@ -418,7 +417,7 @@ def f(a, b, c):
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_FORWARD_IF_TRUE')
+ self.assertInBytecode(f, 'POP_JUMP_IF_TRUE')
def test_elim_jump_to_uncond_jump4(self):
def f():
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst b/Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst
new file mode 100644
index 000000000000..dff12aef721b
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-08-26-18-46-32.gh-issue-93554.QEaCcK.rst
@@ -0,0 +1,16 @@
+Change the jump opcodes so that all conditional jumps are forward jumps.
+Backward jumps are converted by the assembler into a conditional forward
+jump whose target is the fallthrough block (and with a reversed condition),
+followed by an unconditional backward jump. For example:
+
+``POP_JUMP_IF_TRUE BACKWARD_TARGET`` becomes ``POP_JUMP_IF_FALSE NEXT_BLOCK;
+JUMP BACKWARD_TARGET``.
+
+All the directed conditional jump opcodes were removed:
+``POP_JUMP_FORWARD_IF_TRUE``, ``POP_JUMP_BACKWARD_IF_TRUE``,
+``POP_JUMP_FORWARD_IF_FALSE``, ``POP_JUMP_BACKWARD_IF_FALSE``,
+``POP_JUMP_FORWARD_IF_NONE``, ``POP_JUMP_BACKWARD_IF_NONE``,
+``POP_JUMP_FORWARD_IF_NOT_NONE``, ``POP_JUMP_BACKWARD_IF_NOT_NONE``.
+
+The corresponding opcodes without direction are no longer pseudo-instructions,
+and they implement the forward conditional jumps.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index d2647bd12288..2e3777943126 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -311,25 +311,12 @@ mark_stacks(PyCodeObject *code_obj, int len)
switch (opcode) {
case JUMP_IF_FALSE_OR_POP:
case JUMP_IF_TRUE_OR_POP:
- case POP_JUMP_FORWARD_IF_FALSE:
- case POP_JUMP_BACKWARD_IF_FALSE:
- case POP_JUMP_FORWARD_IF_TRUE:
- case POP_JUMP_BACKWARD_IF_TRUE:
+ case POP_JUMP_IF_FALSE:
+ case POP_JUMP_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 ||
- opcode == JUMP_IF_FALSE_OR_POP ||
- opcode == JUMP_IF_TRUE_OR_POP)
- {
- j += i + 1;
- }
- else {
- assert(opcode == POP_JUMP_BACKWARD_IF_FALSE ||
- opcode == POP_JUMP_BACKWARD_IF_TRUE);
- j = i + 1 - j;
- }
+ j += i + 1;
assert(j < len);
if (stacks[j] == UNINITIALIZED && j < i) {
todo = 1;
diff --git a/Python/ceval.c b/Python/ceval.c
index c61ccd7dfc6f..76a81185e76d 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3307,7 +3307,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_FLOAT_JUMP) {
assert(cframe.use_tracing == 0);
- // Combined: COMPARE_OP (float ? float) + POP_JUMP_(direction)_IF_(true/false)
+ // Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
@@ -3325,23 +3325,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
STACK_SHRINK(2);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
- 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;
+ assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
+ int jump = (1 << (sign + 1)) & when_to_jump_mask;
if (!jump) {
next_instr++;
}
- else if (jump >= 8) {
- assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
- opcode == POP_JUMP_BACKWARD_IF_FALSE);
- JUMPBY(1 - oparg);
- CHECK_EVAL_BREAKER();
- }
else {
- assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
- opcode == POP_JUMP_FORWARD_IF_FALSE);
JUMPBY(1 + oparg);
}
NOTRACE_DISPATCH();
@@ -3349,7 +3338,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_INT_JUMP) {
assert(cframe.use_tracing == 0);
- // Combined: COMPARE_OP (int ? int) + POP_JUMP_(direction)_IF_(true/false)
+ // Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false)
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
@@ -3368,23 +3357,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
STACK_SHRINK(2);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
- 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;
+ assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
+ int jump = (1 << (sign + 1)) & when_to_jump_mask;
if (!jump) {
next_instr++;
}
- else if (jump >= 8) {
- assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
- opcode == POP_JUMP_BACKWARD_IF_FALSE);
- JUMPBY(1 - oparg);
- CHECK_EVAL_BREAKER();
- }
else {
- assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
- opcode == POP_JUMP_FORWARD_IF_FALSE);
JUMPBY(1 + oparg);
}
NOTRACE_DISPATCH();
@@ -3392,9 +3370,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_STR_JUMP) {
assert(cframe.use_tracing == 0);
- // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_(direction)_IF_(true/false)
+ // Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false)
_PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
- int when_to_jump_mask = cache->mask;
+ int invert = cache->mask;
PyObject *right = TOP();
PyObject *left = SECOND();
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
@@ -3407,28 +3385,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(oparg == Py_EQ || oparg == Py_NE);
JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
- 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);
+ assert(opcode == POP_JUMP_IF_FALSE || opcode == POP_JUMP_IF_TRUE);
STACK_SHRINK(2);
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
assert(res == 0 || res == 1);
- int sign = 1 - res;
- int jump = (9 << (sign + 1)) & when_to_jump_mask;
+ assert(invert == 0 || invert == 1);
+ int jump = res ^ invert;
if (!jump) {
next_instr++;
}
- else if (jump >= 8) {
- assert(opcode == POP_JUMP_BACKWARD_IF_TRUE ||
- opcode == POP_JUMP_BACKWARD_IF_FALSE);
- JUMPBY(1 - oparg);
- CHECK_EVAL_BREAKER();
- }
else {
- assert(opcode == POP_JUMP_FORWARD_IF_TRUE ||
- opcode == POP_JUMP_FORWARD_IF_FALSE);
JUMPBY(1 + oparg);
}
NOTRACE_DISPATCH();
@@ -3575,34 +3542,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
JUMP_TO_INSTRUCTION(JUMP_BACKWARD_QUICK);
}
- TARGET(POP_JUMP_BACKWARD_IF_FALSE) {
- PREDICTED(POP_JUMP_BACKWARD_IF_FALSE);
- PyObject *cond = POP();
- if (Py_IsTrue(cond)) {
- _Py_DECREF_NO_DEALLOC(cond);
- DISPATCH();
- }
- if (Py_IsFalse(cond)) {
- _Py_DECREF_NO_DEALLOC(cond);
- JUMPBY(-oparg);
- CHECK_EVAL_BREAKER();
- DISPATCH();
- }
- int err = PyObject_IsTrue(cond);
- Py_DECREF(cond);
- if (err > 0)
- ;
- else if (err == 0) {
- JUMPBY(-oparg);
- CHECK_EVAL_BREAKER();
- }
- else
- goto error;
- DISPATCH();
- }
-
- TARGET(POP_JUMP_FORWARD_IF_FALSE) {
- PREDICTED(POP_JUMP_FORWARD_IF_FALSE);
+ TARGET(POP_JUMP_IF_FALSE) {
+ PREDICTED(POP_JUMP_IF_FALSE);
PyObject *cond = POP();
if (Py_IsTrue(cond)) {
_Py_DECREF_NO_DEALLOC(cond);
@@ -3625,32 +3566,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}
- TARGET(POP_JUMP_BACKWARD_IF_TRUE) {
- PyObject *cond = POP();
- if (Py_IsFalse(cond)) {
- _Py_DECREF_NO_DEALLOC(cond);
- DISPATCH();
- }
- if (Py_IsTrue(cond)) {
- _Py_DECREF_NO_DEALLOC(cond);
- JUMPBY(-oparg);
- CHECK_EVAL_BREAKER();
- DISPATCH();
- }
- int err = PyObject_IsTrue(cond);
- Py_DECREF(cond);
- if (err > 0) {
- JUMPBY(-oparg);
- CHECK_EVAL_BREAKER();
- }
- else if (err == 0)
- ;
- else
- goto error;
- DISPATCH();
- }
-
- TARGET(POP_JUMP_FORWARD_IF_TRUE) {
+ TARGET(POP_JUMP_IF_TRUE) {
PyObject *cond = POP();
if (Py_IsFalse(cond)) {
_Py_DECREF_NO_DEALLOC(cond);
@@ -3673,19 +3589,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}
- TARGET(POP_JUMP_BACKWARD_IF_NOT_NONE) {
- PyObject *value = POP();
- if (!Py_IsNone(value)) {
- Py_DECREF(value);
- JUMPBY(-oparg);
- CHECK_EVAL_BREAKER();
- DISPATCH();
- }
- _Py_DECREF_NO_DEALLOC(value);
- DISPATCH();
- }
-
- TARGET(POP_JUMP_FORWARD_IF_NOT_NONE) {
+ TARGET(POP_JUMP_IF_NOT_NONE) {
PyObject *value = POP();
if (!Py_IsNone(value)) {
JUMPBY(oparg);
@@ -3694,20 +3598,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DISPATCH();
}
- TARGET(POP_JUMP_BACKWARD_IF_NONE) {
- PyObject *value = POP();
- if (Py_IsNone(value)) {
- _Py_DECREF_NO_DEALLOC(value);
- JUMPBY(-oparg);
- CHECK_EVAL_BREAKER();
- }
- else {
- Py_DECREF(value);
- }
- DISPATCH();
- }
-
- TARGET(POP_JUMP_FORWARD_IF_NONE) {
+ TARGET(POP_JUMP_IF_NONE) {
PyObject *value = POP();
if (Py_IsNone(value)) {
_Py_DECREF_NO_DEALLOC(value);
@@ -3834,8 +3725,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
PyObject *res = match ? Py_True : Py_False;
Py_INCREF(res);
PUSH(res);
- PREDICT(POP_JUMP_FORWARD_IF_FALSE);
- PREDICT(POP_JUMP_BACKWARD_IF_FALSE);
+ PREDICT(POP_JUMP_IF_FALSE);
DISPATCH();
}
@@ -3845,8 +3735,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
PyObject *res = match ? Py_True : Py_False;
Py_INCREF(res);
PUSH(res);
- PREDICT(POP_JUMP_FORWARD_IF_FALSE);
- PREDICT(POP_JUMP_BACKWARD_IF_FALSE);
+ PREDICT(POP_JUMP_IF_FALSE);
DISPATCH();
}
diff --git a/Python/compile.c b/Python/compile.c
index 857fca440ac0..862999d87b85 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -96,23 +96,11 @@
#define IS_ASSEMBLER_OPCODE(opcode) \
((opcode) == JUMP_FORWARD || \
(opcode) == JUMP_BACKWARD || \
- (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)
+ (opcode) == JUMP_BACKWARD_NO_INTERRUPT)
#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)
+ (opcode) == JUMP_BACKWARD_NO_INTERRUPT)
#define IS_UNCONDITIONAL_JUMP_OPCODE(opcode) \
((opcode) == JUMP || \
@@ -1146,17 +1134,9 @@ stack_effect(int opcode, int oparg, int jump)
case JUMP_IF_FALSE_OR_POP:
return jump ? 0 : -1;
- 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;
@@ -7747,63 +7727,91 @@ assemble_emit(struct assembler *a, struct instr *i)
return 1;
}
-static void
-normalize_jumps(basicblock *entryblock)
+static int
+normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
+ struct instr *last = basicblock_last_instr(b);
+ if (last == NULL || !is_jump(last)) {
+ return 0;
+ }
+ assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
+ bool is_forward = last->i_target->b_visited == 0;
+ switch(last->i_opcode) {
+ case JUMP:
+ last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
+ return 0;
+ case JUMP_NO_INTERRUPT:
+ last->i_opcode = is_forward ?
+ JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
+ return 0;
+ }
+ int reversed_opcode = 0;
+ switch(last->i_opcode) {
+ case POP_JUMP_IF_NOT_NONE:
+ reversed_opcode = POP_JUMP_IF_NONE;
+ break;
+ case POP_JUMP_IF_NONE:
+ reversed_opcode = POP_JUMP_IF_NOT_NONE;
+ break;
+ case POP_JUMP_IF_FALSE:
+ reversed_opcode = POP_JUMP_IF_TRUE;
+ break;
+ case POP_JUMP_IF_TRUE:
+ reversed_opcode = POP_JUMP_IF_FALSE;
+ break;
+ case JUMP_IF_TRUE_OR_POP:
+ case JUMP_IF_FALSE_OR_POP:
+ if (!is_forward) {
+ /* As far as we can tell, the compiler never emits
+ * these jumps with a backwards target. If/when this
+ * exception is raised, we have found a use case for
+ * a backwards version of this jump (or to replace
+ * it with the sequence (COPY 1, POP_JUMP_IF_T/F, POP)
+ */
+ PyErr_Format(PyExc_SystemError,
+ "unexpected %s jumping backwards",
+ last->i_opcode == JUMP_IF_TRUE_OR_POP ?
+ "JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP");
+ }
+ return 0;
+ }
+ if (is_forward) {
+ return 0;
+ }
+
+ /* transform 'conditional jump T' to
+ * 'reversed_jump b_next' followed by 'jump_backwards T'
+ */
+
+ basicblock *target = last->i_target;
+ basicblock *backwards_jump = cfg_builder_new_block(g);
+ if (backwards_jump == NULL) {
+ return -1;
+ }
+ basicblock_addop(backwards_jump, JUMP, target->b_label, NO_LOCATION);
+ backwards_jump->b_instr[0].i_target = target;
+ last->i_opcode = reversed_opcode;
+ last->i_target = b->b_next;
+
+ backwards_jump->b_cold = b->b_cold;
+ backwards_jump->b_next = b->b_next;
+ b->b_next = backwards_jump;
+ return 0;
+}
+
+static int
+normalize_jumps(cfg_builder *g)
{
+ basicblock *entryblock = g->g_entryblock;
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
b->b_visited = 0;
}
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
b->b_visited = 1;
- struct instr *last = basicblock_last_instr(b);
- if (last == NULL) {
- continue;
- }
- assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
- if (is_jump(last)) {
- bool is_forward = last->i_target->b_visited == 0;
- 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;
- case JUMP_IF_TRUE_OR_POP:
- case JUMP_IF_FALSE_OR_POP:
- if (!is_forward) {
- /* As far as we can tell, the compiler never emits
- * these jumps with a backwards target. If/when this
- * exception is raised, we have found a use case for
- * a backwards version of this jump (or to replace
- * it with the sequence (COPY 1, POP_JUMP_IF_T/F, POP)
- */
- PyErr_Format(PyExc_SystemError,
- "unexpected %s jumping backwards",
- last->i_opcode == JUMP_IF_TRUE_OR_POP ?
- "JUMP_IF_TRUE_OR_POP" : "JUMP_IF_FALSE_OR_POP");
- }
- break;
- }
+ if (normalize_jumps_in_block(g, b) < 0) {
+ return -1;
}
}
+ return 0;
}
static void
@@ -8638,7 +8646,9 @@ assemble(struct compiler *c, int addNone)
}
/* Order of basic blocks must have been determined by now */
- normalize_jumps(g->g_entryblock);
+ if (normalize_jumps(g) < 0) {
+ goto error;
+ }
if (add_checks_for_loads_of_unknown_variables(g->g_entryblock, c) < 0) {
goto error;
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 7c782d101c1b..c1ff367d4fd3 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -113,8 +113,8 @@ static void *opcode_targets[256] = {
&&TARGET_JUMP_IF_FALSE_OR_POP,
&&TARGET_JUMP_IF_TRUE_OR_POP,
&&TARGET_LOAD_ATTR_METHOD_NO_DICT,
- &&TARGET_POP_JUMP_FORWARD_IF_FALSE,
- &&TARGET_POP_JUMP_FORWARD_IF_TRUE,
+ &&TARGET_POP_JUMP_IF_FALSE,
+ &&TARGET_POP_JUMP_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_LOAD_FAST_CHECK,
- &&TARGET_POP_JUMP_FORWARD_IF_NOT_NONE,
- &&TARGET_POP_JUMP_FORWARD_IF_NONE,
+ &&TARGET_POP_JUMP_IF_NOT_NONE,
+ &&TARGET_POP_JUMP_IF_NONE,
&&TARGET_RAISE_VARARGS,
&&TARGET_GET_AWAITABLE,
&&TARGET_MAKE_FUNCTION,
@@ -172,10 +172,6 @@ static void *opcode_targets[256] = {
&&TARGET_STORE_FAST__LOAD_FAST,
&&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_STORE_FAST__STORE_FAST,
&&TARGET_STORE_SUBSCR_ADAPTIVE,
&&TARGET_STORE_SUBSCR_DICT,
@@ -254,5 +250,9 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
+ &&_unknown_opcode,
+ &&_unknown_opcode,
+ &&_unknown_opcode,
+ &&_unknown_opcode,
&&TARGET_DO_TRACING
};
diff --git a/Python/specialize.c b/Python/specialize.c
index 8a2f9054cad5..e8c3f468feaa 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -1999,10 +1999,8 @@ _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_FORWARD_IF_FALSE &&
- next_opcode != POP_JUMP_BACKWARD_IF_FALSE &&
- next_opcode != POP_JUMP_FORWARD_IF_TRUE &&
- next_opcode != POP_JUMP_BACKWARD_IF_TRUE) {
+ if (next_opcode != POP_JUMP_IF_FALSE &&
+ next_opcode != POP_JUMP_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
@@ -2021,14 +2019,9 @@ _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_FORWARD_IF_FALSE ||
- next_opcode == POP_JUMP_BACKWARD_IF_FALSE) {
+ if (next_opcode == POP_JUMP_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;
@@ -2056,7 +2049,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;
+ cache->mask = (when_to_jump_mask & 2) == 0;
goto success;
}
}
1
0
01 Sep '22
https://github.com/python/cpython/commit/bb8e49b4203fc1f2df554b452dbd392610…
commit: bb8e49b4203fc1f2df554b452dbd3926102b18ee
branch: 3.7
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: ned-deily <nad(a)python.org>
date: 2022-09-01T15:23:27-04:00
summary:
bpo-41306: Allow scale value to not be rounded (GH-21715) (GH-96484)
This fixes the test failure with Tk 6.8.10 which is caused by changes to how Tk rounds the `from`, `to` and `tickinterval` arguments. This PR uses `noconv` if the patchlevel is greater than or equal to 8.6.10 (credit to Serhiy for this idea as it is much simpler than what I previously proposed).
Going into more detail for those who want it, the Tk change was made in [commit 591f68c](https://github.com/tcltk/tk/commit/591f68cb382525b72664c6fecaab877… and means that the arguments listed above are rounded relative to the value of `from`. However, when rounding the `from` argument ([line 623](https://github.com/tcltk/tk/blob/591f68cb382525b72664c6fecaab87742b6cc…), it is rounded relative to itself (i.e. rounding `0`) and therefore the assigned value for `from` is always what is given (no matter what values of `from` and `resolution`).
Automerge-Triggered-By: @pablogsal
(cherry picked from commit aecf036738a404371303e770f4ce4fd9f7d43de7)
Co-authored-by: E-Paine <63801254+E-Paine(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Tests/2020-08-03-13-44-37.bpo-41306.VDoWXI.rst
M Lib/tkinter/test/test_tkinter/test_widgets.py
diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py
index 3fb641108cf8..5cfab683205d 100644
--- a/Lib/tkinter/test/test_tkinter/test_widgets.py
+++ b/Lib/tkinter/test/test_tkinter/test_widgets.py
@@ -864,7 +864,8 @@ def test_digits(self):
def test_from(self):
widget = self.create()
- self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round)
+ conv = False if get_tk_patchlevel() >= (8, 6, 10) else float_round
+ self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=conv)
def test_label(self):
widget = self.create()
diff --git a/Misc/NEWS.d/next/Tests/2020-08-03-13-44-37.bpo-41306.VDoWXI.rst b/Misc/NEWS.d/next/Tests/2020-08-03-13-44-37.bpo-41306.VDoWXI.rst
new file mode 100644
index 000000000000..5e9ba2d8a274
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2020-08-03-13-44-37.bpo-41306.VDoWXI.rst
@@ -0,0 +1 @@
+Fixed a failure in ``test_tk.test_widgets.ScaleTest`` happening when executing the test with Tk 8.6.10.
1
0
gh-96455: update example in exception_handling_notes.txt to the 3.11RC bytecode (GH-96456)
by miss-islington 01 Sep '22
by miss-islington 01 Sep '22
01 Sep '22
https://github.com/python/cpython/commit/583591134c2a7c09a288d0a62dd1bd9272…
commit: 583591134c2a7c09a288d0a62dd1bd92728621aa
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2022-09-01T06:45:09-07:00
summary:
gh-96455: update example in exception_handling_notes.txt to the 3.11RC bytecode (GH-96456)
(cherry picked from commit a91f25577c71ab8797a4b42f22c43bbaffc2604d)
Co-authored-by: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
files:
M Objects/exception_handling_notes.txt
diff --git a/Objects/exception_handling_notes.txt b/Objects/exception_handling_notes.txt
index a136358f90c8..7de01fdbf5ff 100644
--- a/Objects/exception_handling_notes.txt
+++ b/Objects/exception_handling_notes.txt
@@ -43,33 +43,36 @@ SETUP_FINALLY and POP_BLOCK.
In 3.11, the SETUP_FINALLY and POP_BLOCK are eliminated, replaced with
a table to determine where to jump to when an exception is raised.
- 2 0 NOP
-
- 3 2 LOAD_GLOBAL 0 (g)
- 4 LOAD_CONST 1 (0)
- 6 CALL_NO_KW 1
- 8 POP_TOP
- 10 LOAD_CONST 0 (None)
- 12 RETURN_VALUE
- >> 14 PUSH_EXC_INFO
-
- 4 16 POP_TOP
- 18 POP_TOP
- 20 POP_TOP
-
- 5 22 POP_EXCEPT
- 24 LOAD_CONST 2 ('fail')
- 26 RETURN_VALUE
- >> 28 POP_EXCEPT_AND_RERAISE
+ 1 0 RESUME 0
+
+ 2 2 NOP
+
+ 3 4 LOAD_GLOBAL 1 (NULL + g)
+ 16 LOAD_CONST 1 (0)
+ 18 PRECALL 1
+ 22 CALL 1
+ 32 POP_TOP
+ 34 LOAD_CONST 0 (None)
+ 36 RETURN_VALUE
+ >> 38 PUSH_EXC_INFO
+
+ 4 40 POP_TOP
+
+ 5 42 POP_EXCEPT
+ 44 LOAD_CONST 2 ('fail')
+ 46 RETURN_VALUE
+ >> 48 COPY 3
+ 50 POP_EXCEPT
+ 52 RERAISE 1
ExceptionTable:
- 2 to 8 -> 14 [0]
- 14 to 20 -> 28 [3] lasti
+ 4 to 32 -> 38 [0]
+ 38 to 40 -> 48 [1] lasti
-(Note this code is from an early 3.11 alpha, the NOP may well have be removed before release).
+(Note this code is from 3.11, later versions may have slightly different bytecode.)
If an instruction raises an exception then its offset is used to find the target to jump to.
-For example, the CALL_NO_KW at offset 6, falls into the range 2 to 8.
-So, if g() raises an exception, then control jumps to offset 14.
+For example, the CALL at offset 22, falls into the range 4 to 32.
+So, if g() raises an exception, then control jumps to offset 38.
Unwinding
@@ -84,9 +87,9 @@ This information is stored in the exception table, described below.
If there is no relevant entry, the exception bubbles up to the caller.
If there is an entry, then:
- 1. pop values from the stack until it matches the stack depth for the handler,
+ 1. pop values from the stack until it matches the stack depth for the handler.
2. if 'lasti' is true, then push the offset that the exception was raised at.
- 3. push the exception to the stack as three values: traceback, value, type,
+ 3. push the exception to the stack.
4. jump to the target offset and resume execution.
1
0
gh-96455: update example in exception_handling_notes.txt to the 3.11RC bytecode (GH-96456)
by iritkatriel 01 Sep '22
by iritkatriel 01 Sep '22
01 Sep '22
https://github.com/python/cpython/commit/a91f25577c71ab8797a4b42f22c43bbaff…
commit: a91f25577c71ab8797a4b42f22c43bbaffc2604d
branch: main
author: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel(a)users.noreply.github.com>
date: 2022-09-01T14:21:39+01:00
summary:
gh-96455: update example in exception_handling_notes.txt to the 3.11RC bytecode (GH-96456)
files:
M Objects/exception_handling_notes.txt
diff --git a/Objects/exception_handling_notes.txt b/Objects/exception_handling_notes.txt
index a136358f90c8..7de01fdbf5ff 100644
--- a/Objects/exception_handling_notes.txt
+++ b/Objects/exception_handling_notes.txt
@@ -43,33 +43,36 @@ SETUP_FINALLY and POP_BLOCK.
In 3.11, the SETUP_FINALLY and POP_BLOCK are eliminated, replaced with
a table to determine where to jump to when an exception is raised.
- 2 0 NOP
-
- 3 2 LOAD_GLOBAL 0 (g)
- 4 LOAD_CONST 1 (0)
- 6 CALL_NO_KW 1
- 8 POP_TOP
- 10 LOAD_CONST 0 (None)
- 12 RETURN_VALUE
- >> 14 PUSH_EXC_INFO
-
- 4 16 POP_TOP
- 18 POP_TOP
- 20 POP_TOP
-
- 5 22 POP_EXCEPT
- 24 LOAD_CONST 2 ('fail')
- 26 RETURN_VALUE
- >> 28 POP_EXCEPT_AND_RERAISE
+ 1 0 RESUME 0
+
+ 2 2 NOP
+
+ 3 4 LOAD_GLOBAL 1 (NULL + g)
+ 16 LOAD_CONST 1 (0)
+ 18 PRECALL 1
+ 22 CALL 1
+ 32 POP_TOP
+ 34 LOAD_CONST 0 (None)
+ 36 RETURN_VALUE
+ >> 38 PUSH_EXC_INFO
+
+ 4 40 POP_TOP
+
+ 5 42 POP_EXCEPT
+ 44 LOAD_CONST 2 ('fail')
+ 46 RETURN_VALUE
+ >> 48 COPY 3
+ 50 POP_EXCEPT
+ 52 RERAISE 1
ExceptionTable:
- 2 to 8 -> 14 [0]
- 14 to 20 -> 28 [3] lasti
+ 4 to 32 -> 38 [0]
+ 38 to 40 -> 48 [1] lasti
-(Note this code is from an early 3.11 alpha, the NOP may well have be removed before release).
+(Note this code is from 3.11, later versions may have slightly different bytecode.)
If an instruction raises an exception then its offset is used to find the target to jump to.
-For example, the CALL_NO_KW at offset 6, falls into the range 2 to 8.
-So, if g() raises an exception, then control jumps to offset 14.
+For example, the CALL at offset 22, falls into the range 4 to 32.
+So, if g() raises an exception, then control jumps to offset 38.
Unwinding
@@ -84,9 +87,9 @@ This information is stored in the exception table, described below.
If there is no relevant entry, the exception bubbles up to the caller.
If there is an entry, then:
- 1. pop values from the stack until it matches the stack depth for the handler,
+ 1. pop values from the stack until it matches the stack depth for the handler.
2. if 'lasti' is true, then push the offset that the exception was raised at.
- 3. push the exception to the stack as three values: traceback, value, type,
+ 3. push the exception to the stack.
4. jump to the target offset and resume execution.
1
0
01 Sep '22
https://github.com/python/cpython/commit/894cafd9a53f2423adc6b1fb111006883a…
commit: 894cafd9a53f2423adc6b1fb111006883aeac03c
branch: main
author: Irit Katriel <1055913+iritkatriel(a)users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel(a)users.noreply.github.com>
date: 2022-09-01T11:03:52+01:00
summary:
gh-93678: apply remove_redundant_jumps in optimize_cfg (GH-96274)
files:
M Lib/test/test_peepholer.py
M Python/compile.c
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py
index 7ece468363be..7cd9b060f5e9 100644
--- a/Lib/test/test_peepholer.py
+++ b/Lib/test/test_peepholer.py
@@ -892,7 +892,8 @@ def test_conditional_jump_forward_non_const_condition(self):
self.cfg_optimization_test(insts, expected, consts=list(range(5)))
def test_conditional_jump_forward_const_condition(self):
- # The unreachable branch of the jump is removed
+ # The unreachable branch of the jump is removed, the jump
+ # becomes redundant and is replaced by a NOP (for the lineno)
insts = [
('LOAD_CONST', 3, 11),
@@ -903,8 +904,7 @@ def test_conditional_jump_forward_const_condition(self):
]
expected = [
('NOP', None, 11),
- ('JUMP', lbl := self.Label(), 12),
- lbl,
+ ('NOP', None, 12),
('LOAD_CONST', '3', 14)
]
self.cfg_optimization_test(insts, expected, consts=list(range(5)))
diff --git a/Python/compile.c b/Python/compile.c
index 627f86a8ce91..857fca440ac0 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -7396,6 +7396,9 @@ mark_cold(basicblock *entryblock) {
return 0;
}
+static int
+remove_redundant_jumps(cfg_builder *g);
+
static int
push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
basicblock *entryblock = g->g_entryblock;
@@ -7465,6 +7468,12 @@ push_cold_blocks_to_end(cfg_builder *g, int code_flags) {
}
assert(b != NULL && b->b_next == NULL);
b->b_next = cold_blocks;
+
+ if (cold_blocks != NULL) {
+ if (remove_redundant_jumps(g) < 0) {
+ return -1;
+ }
+ }
return 0;
}
@@ -8269,9 +8278,6 @@ trim_unused_consts(basicblock *entryblock, PyObject *consts);
static int
duplicate_exits_without_lineno(cfg_builder *g);
-static int
-extend_block(basicblock *bb);
-
static int *
build_cellfixedoffsets(struct compiler *c)
{
@@ -8476,6 +8482,21 @@ propagate_line_numbers(basicblock *entryblock);
static void
eliminate_empty_basic_blocks(cfg_builder *g);
+#ifndef NDEBUG
+static bool
+no_redundant_jumps(cfg_builder *g) {
+ for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
+ struct instr *last = basicblock_last_instr(b);
+ if (last != NULL) {
+ if (last->i_opcode == JUMP || last->i_opcode == JUMP_NO_INTERRUPT) {
+ assert(last->i_target != b->b_next);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+#endif
static int
remove_redundant_jumps(cfg_builder *g) {
@@ -8592,8 +8613,8 @@ assemble(struct compiler *c, int addNone)
if (trim_unused_consts(g->g_entryblock, consts)) {
goto error;
}
- if (duplicate_exits_without_lineno(g)) {
- return NULL;
+ if (duplicate_exits_without_lineno(g) < 0) {
+ goto error;
}
propagate_line_numbers(g->g_entryblock);
guarantee_lineno_for_exits(g->g_entryblock, c->u->u_firstlineno);
@@ -8612,10 +8633,6 @@ assemble(struct compiler *c, int addNone)
if (push_cold_blocks_to_end(g, code_flags) < 0) {
goto error;
}
-
- if (remove_redundant_jumps(g) < 0) {
- goto error;
- }
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
clean_basic_block(b);
}
@@ -8627,6 +8644,8 @@ assemble(struct compiler *c, int addNone)
goto error;
}
+ assert(no_redundant_jumps(g));
+
/* Can't modify the bytecode after computing jump offsets. */
assemble_jump_offsets(g->g_entryblock);
@@ -9488,7 +9507,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
}
}
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
- if (extend_block(b)) {
+ if (extend_block(b) < 0) {
return -1;
}
}
@@ -9500,7 +9519,7 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
assert(b->b_predecessors == 0);
}
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
- if (extend_block(b)) {
+ if (extend_block(b) < 0) {
return -1;
}
}
@@ -9517,6 +9536,9 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
clean_basic_block(b);
}
+ if (remove_redundant_jumps(g) < 0) {
+ return -1;
+ }
return 0;
}
1
0
01 Sep '22
https://github.com/python/cpython/commit/e93d1bda77b71db7ca150187f841fbb237…
commit: e93d1bda77b71db7ca150187f841fbb237772b2c
branch: main
author: Gregory P. Smith <greg(a)krypto.org>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2022-09-01T02:47:40-07:00
summary:
gh-96143: subprocess API %s/universal_newlines=/text=/g. (GH-96468)
minor missed test cleanup to use the modern API from the big review.
Automerge-Triggered-By: GH:gpshead
files:
M Lib/test/test_perf_profiler.py
diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py
index f587995b008f..2b977d78d393 100644
--- a/Lib/test/test_perf_profiler.py
+++ b/Lib/test/test_perf_profiler.py
@@ -108,7 +108,7 @@ def baz():
script = make_script(script_dir, "perftest", code)
with subprocess.Popen(
[sys.executable, "-Xperf", script],
- universal_newlines=True,
+ text=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
) as process:
@@ -157,7 +157,7 @@ def baz():
script = make_script(script_dir, "perftest", code)
with subprocess.Popen(
[sys.executable, script],
- universal_newlines=True,
+ text=True,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
) as process:
@@ -211,7 +211,7 @@ def is_unwinding_reliable():
def perf_command_works():
try:
cmd = ["perf", "--help"]
- stdout = subprocess.check_output(cmd, universal_newlines=True)
+ stdout = subprocess.check_output(cmd, text=True)
except (subprocess.SubprocessError, OSError):
return False
@@ -237,7 +237,7 @@ def perf_command_works():
'print("hello")',
)
stdout = subprocess.check_output(
- cmd, cwd=script_dir, universal_newlines=True, stderr=subprocess.STDOUT
+ cmd, cwd=script_dir, text=True, stderr=subprocess.STDOUT
)
except (subprocess.SubprocessError, OSError):
return False
1
0