From d48b0266178ae47b13160fe90a3fa393366ccdbf Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 31 Mar 2022 22:37:25 +0100 Subject: [PATCH 1/7] bpo-47120: replace JUMP_NO_INTERRUPT by the relative JUMP_BACKWARD_NO_INTERRUPT --- Doc/library/dis.rst | 14 +++++++------- Include/opcode.h | 6 +++--- Lib/importlib/_bootstrap_external.py | 4 +++- Lib/opcode.py | 2 +- Lib/test/test_dis.py | 3 ++- Objects/frameobject.c | 14 +++++--------- Python/ceval.c | 4 ++-- Python/compile.c | 14 ++++++++------ Python/opcode_targets.h | 2 +- 9 files changed, 32 insertions(+), 31 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index d1a0cecd82841f..255812154567e1 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -902,6 +902,13 @@ iterations of the loop. .. versionadded:: 3.11 +.. opcode:: JUMP_BACKWARD_NO_INTERRUPT (delta) + + Decrements bytecode counter by *delta*. Does not check for interrupts. + + .. versionadded:: 3.11 + + .. opcode:: POP_JUMP_IF_TRUE (target) If TOS is true, sets the bytecode counter to *target*. TOS is popped. @@ -981,13 +988,6 @@ iterations of the loop. .. versionadded:: 3.1 -.. opcode:: JUMP_NO_INTERRUPT (target) - - Set bytecode counter to *target*. Do not check for interrupts. - - .. versionadded:: 3.11 - - .. opcode:: FOR_ITER (delta) TOS is an :term:`iterator`. Call its :meth:`~iterator.__next__` method. If diff --git a/Include/opcode.h b/Include/opcode.h index 3a7db438ede1f3..ded3a95da298b3 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -87,7 +87,7 @@ extern "C" { #define GET_AWAITABLE 131 #define MAKE_FUNCTION 132 #define BUILD_SLICE 133 -#define JUMP_NO_INTERRUPT 134 +#define JUMP_BACKWARD_NO_INTERRUPT 134 #define MAKE_CELL 135 #define LOAD_CLOSURE 136 #define LOAD_DEREF 137 @@ -196,7 +196,7 @@ static const uint32_t _PyOpcode_RelativeJump[8] = { 0U, 536870912U, 134234112U, - 4096U, + 4160U, 0U, 0U, 0U, @@ -290,13 +290,13 @@ const uint8_t _PyOpcode_Deopt[256] = { [IMPORT_STAR] = IMPORT_STAR, [IS_OP] = IS_OP, [JUMP_BACKWARD] = JUMP_BACKWARD, + [JUMP_BACKWARD_NO_INTERRUPT] = JUMP_BACKWARD_NO_INTERRUPT, [JUMP_BACKWARD_QUICK] = JUMP_BACKWARD, [JUMP_FORWARD] = JUMP_FORWARD, [JUMP_IF_FALSE_OR_POP] = JUMP_IF_FALSE_OR_POP, [JUMP_IF_NOT_EG_MATCH] = JUMP_IF_NOT_EG_MATCH, [JUMP_IF_NOT_EXC_MATCH] = JUMP_IF_NOT_EXC_MATCH, [JUMP_IF_TRUE_OR_POP] = JUMP_IF_TRUE_OR_POP, - [JUMP_NO_INTERRUPT] = JUMP_NO_INTERRUPT, [KW_NAMES] = KW_NAMES, [LIST_APPEND] = LIST_APPEND, [LIST_EXTEND] = LIST_EXTEND, diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 744fefd5e21e79..77a3808e7ba94f 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -397,6 +397,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a6 3487 (Remove the adaptive "oparg counter" mechanism) # Python 3.11a6 3488 (LOAD_GLOBAL can push additional NULL) # Python 3.11a6 3489 (Add JUMP_BACKWARD, remove JUMP_ABSOLUTE) +# Python 3.11a6 3490 (Add JUMP_BACKWARD_NO_INTERRUPT, remove JUMP_NO_INTERRUPT) # Python 3.12 will start with magic number 3500 @@ -411,7 +412,8 @@ 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 = (3489).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3490).to_bytes(2, 'little') + b'\r\n' + _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index 6bc64177ac8fc6..7392064f8f911a 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -154,7 +154,7 @@ def jabs_op(name, op, entries=0): def_op('GET_AWAITABLE', 131) def_op('MAKE_FUNCTION', 132) # Flags def_op('BUILD_SLICE', 133) # Number of items -jabs_op('JUMP_NO_INTERRUPT', 134) # Target byte offset from beginning of code +jrel_op('JUMP_BACKWARD_NO_INTERRUPT', 134) # Number of words to skip (backwards) def_op('MAKE_CELL', 135) hasfree.append(135) def_op('LOAD_CLOSURE', 136) diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 99db8ba0ac3b9a..0f1df7920270f7 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -684,7 +684,8 @@ def test_widths(self): for opcode, opname in enumerate(dis.opname): if opname in ('BUILD_MAP_UNPACK_WITH_CALL', 'BUILD_TUPLE_UNPACK_WITH_CALL', - 'JUMP_IF_NOT_EXC_MATCH'): + 'JUMP_IF_NOT_EXC_MATCH', + 'JUMP_BACKWARD_NO_INTERRUPT'): continue with self.subTest(opname=opname): width = dis._OPNAME_WIDTH diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 581de22587219b..498832711b7454 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -237,15 +237,6 @@ mark_stacks(PyCodeObject *code_obj, int len) stacks[i+1] = next_stack; break; } - case JUMP_NO_INTERRUPT: - j = get_arg(code, i); - assert(j < len); - if (stacks[j] == UNINITIALIZED && j < i) { - todo = 1; - } - assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack); - stacks[j] = next_stack; - break; case POP_EXCEPT: next_stack = pop_value(pop_value(pop_value(next_stack))); stacks[i+1] = next_stack; @@ -264,8 +255,13 @@ mark_stacks(PyCodeObject *code_obj, int len) stacks[j] = next_stack; break; case JUMP_BACKWARD: + case JUMP_BACKWARD_NO_INTERRUPT: j = i + 1 - get_arg(code, i); assert(j >= 0); + assert(j < len); + if (stacks[j] == UNINITIALIZED && j < i) { + todo = 1; + } assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack); stacks[j] = next_stack; break; diff --git a/Python/ceval.c b/Python/ceval.c index 8f73ea1c01ac5d..f441a705eb540e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4058,13 +4058,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int DISPATCH(); } - TARGET(JUMP_NO_INTERRUPT) { + TARGET(JUMP_BACKWARD_NO_INTERRUPT) { /* This bytecode is used in the `yield from` or `await` loop. * If there is an interrupt, we want it handled in the innermost * generator or coroutine, so we deliberately do not check it here. * (see bpo-30039). */ - JUMPTO(oparg); + JUMPBY(-oparg); DISPATCH(); } diff --git a/Python/compile.c b/Python/compile.c index 7a073777ee1cf2..2b746bccf329f3 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -990,7 +990,7 @@ stack_effect(int opcode, int oparg, int jump) case JUMP_FORWARD: case JUMP_BACKWARD: case JUMP: - case JUMP_NO_INTERRUPT: + case JUMP_BACKWARD_NO_INTERRUPT: return 0; case JUMP_IF_TRUE_OR_POP: @@ -1891,7 +1891,7 @@ compiler_add_yield_from(struct compiler *c, int await) compiler_use_next_block(c, resume); ADDOP(c, YIELD_VALUE); ADDOP_I(c, RESUME, await ? 3 : 2); - ADDOP_JUMP(c, JUMP_NO_INTERRUPT, start); + ADDOP_JUMP(c, JUMP_BACKWARD_NO_INTERRUPT, start); compiler_use_next_block(c, exit); return 1; } @@ -7051,7 +7051,7 @@ stackdepth(struct compiler *c) depth = new_depth; assert(instr->i_opcode != JUMP_FORWARD); assert(instr->i_opcode != JUMP_BACKWARD); - if (instr->i_opcode == JUMP_NO_INTERRUPT || + if (instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT || instr->i_opcode == JUMP || instr->i_opcode == RETURN_VALUE || instr->i_opcode == RAISE_VARARGS || @@ -7608,11 +7608,13 @@ 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); + assert(instr->i_opcode == JUMP_BACKWARD || + instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT); instr->i_oparg = bsize - instr->i_oparg; } else { assert(instr->i_opcode != JUMP_BACKWARD); + assert(instr->i_opcode != JUMP_BACKWARD_NO_INTERRUPT); instr->i_oparg -= bsize; } } @@ -8951,7 +8953,7 @@ normalize_basic_block(basicblock *bb) { bb->b_nofallthrough = 1; break; case JUMP: - case JUMP_NO_INTERRUPT: + case JUMP_BACKWARD_NO_INTERRUPT: bb->b_nofallthrough = 1; /* fall through */ case POP_JUMP_IF_NOT_NONE: @@ -9138,7 +9140,7 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) assert(b_last_instr->i_opcode != JUMP_FORWARD); assert(b_last_instr->i_opcode != JUMP_BACKWARD); if (b_last_instr->i_opcode == JUMP || - b_last_instr->i_opcode == JUMP_NO_INTERRUPT) { + b_last_instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT) { if (b_last_instr->i_target == b->b_next) { assert(b->b_next->b_iused); b->b_nofallthrough = 0; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 3afaf0b0298314..fb7440ca5e6368 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -133,7 +133,7 @@ static void *opcode_targets[256] = { &&TARGET_GET_AWAITABLE, &&TARGET_MAKE_FUNCTION, &&TARGET_BUILD_SLICE, - &&TARGET_JUMP_NO_INTERRUPT, + &&TARGET_JUMP_BACKWARD_NO_INTERRUPT, &&TARGET_MAKE_CELL, &&TARGET_LOAD_CLOSURE, &&TARGET_LOAD_DEREF, From 588bab79ab5603dd7b9d8830846b15901d8e822c Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 31 Mar 2022 21:43:59 +0000 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core and Builtins/2022-03-31-21-43-57.bpo-47120.NgxQbA.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-03-31-21-43-57.bpo-47120.NgxQbA.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-31-21-43-57.bpo-47120.NgxQbA.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-31-21-43-57.bpo-47120.NgxQbA.rst new file mode 100644 index 00000000000000..236ad947950560 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-31-21-43-57.bpo-47120.NgxQbA.rst @@ -0,0 +1 @@ +Replace the absolute jump opcode :opcode:`JUMP_NO_INTERRUPT` by the relative :opcode:`JUMP_BACKWARD_NO_INTERRUPT`. From 50c507b62e762bb1a2e19e53b2680589cd2c4fb3 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 31 Mar 2022 22:45:28 +0100 Subject: [PATCH 3/7] update whatsnew --- Doc/whatsnew/3.11.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 16715c32502e40..62f79df9186460 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -524,6 +524,9 @@ CPython bytecode changes * Replaced :opcode:`JUMP_ABSOLUTE` by the relative :opcode:`JUMP_BACKWARD`. +* Replaced :opcode:`JUMP_NO_INTERRUPT` by the relative + :opcode:`JUMP_BACKWARD_NO_INTERRUPT`. + Deprecated ========== From bcdefdfbcde62c44c956a73583b986d986d83b4d Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Thu, 31 Mar 2022 22:57:51 +0100 Subject: [PATCH 4/7] Update Doc/whatsnew/3.11.rst --- Doc/whatsnew/3.11.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 62f79df9186460..b4c0b31fe9615b 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -524,8 +524,7 @@ CPython bytecode changes * Replaced :opcode:`JUMP_ABSOLUTE` by the relative :opcode:`JUMP_BACKWARD`. -* Replaced :opcode:`JUMP_NO_INTERRUPT` by the relative - :opcode:`JUMP_BACKWARD_NO_INTERRUPT`. +* Added :opcode:`JUMP_BACKWARD_NO_INTERRUPT`, which is used in certain loops where it is undesirable to handle interrupts. Deprecated ========== From 0a418d36442119ae879e8b2faf1a51373cf08b78 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 1 Apr 2022 17:48:49 +0100 Subject: [PATCH 5/7] make JUMP_NO_INTERRUPT virutal, mapped to JUMP_FORWARD or JUMP_BACKWARD_NO_INTERRUPT by assembler --- Lib/importlib/_bootstrap_external.py | 3 +- Lib/test/test_dis.py | 3 +- Python/compile.c | 53 ++++++++++++++++------------ 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 39a348aecef6c3..af367b20b5a9ae 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -398,6 +398,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a6 3488 (LOAD_GLOBAL can push additional NULL) # Python 3.11a6 3489 (Add JUMP_BACKWARD, remove JUMP_ABSOLUTE) # Python 3.11a6 3490 (remove JUMP_IF_NOT_EXC_MATCH, add CHECK_EXC_MATCH) +# Python 3.11a6 3491 (Add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual) # Python 3.12 will start with magic number 3500 @@ -412,7 +413,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 = (3490).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3491).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 544e1350cb7f9e..2f78d42cc724a6 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -684,7 +684,8 @@ def test_boundaries(self): def test_widths(self): for opcode, opname in enumerate(dis.opname): if opname in ('BUILD_MAP_UNPACK_WITH_CALL', - 'BUILD_TUPLE_UNPACK_WITH_CALL'): + 'BUILD_TUPLE_UNPACK_WITH_CALL', + 'JUMP_BACKWARD_NO_INTERRUPT'): continue with self.subTest(opname=opname): width = dis._OPNAME_WIDTH diff --git a/Python/compile.c b/Python/compile.c index 7612a3f950f556..5fba6612560dad 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -77,8 +77,9 @@ #define SETUP_WITH -3 #define POP_BLOCK -4 #define JUMP -5 +#define JUMP_NO_INTERRUPT -6 -#define MIN_VIRTUAL_OPCODE -5 +#define MIN_VIRTUAL_OPCODE -6 #define MAX_ALLOWED_OPCODE 254 #define IS_WITHIN_OPCODE_RANGE(opcode) \ @@ -86,6 +87,13 @@ #define IS_VIRTUAL_OPCODE(opcode) ((opcode) < 0) +/* 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) + + #define IS_TOP_LEVEL_AWAIT(c) ( \ (c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) \ && (c->u->u_ste->ste_type == ModuleBlock)) @@ -1012,6 +1020,7 @@ stack_effect(int opcode, int oparg, int jump) case JUMP_BACKWARD: case JUMP: case JUMP_BACKWARD_NO_INTERRUPT: + case JUMP_NO_INTERRUPT: return 0; case JUMP_IF_TRUE_OR_POP: @@ -1199,6 +1208,7 @@ compiler_addop_line(struct compiler *c, int opcode, int line, int end_line, int col_offset, int end_col_offset) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); + assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(!HAS_ARG(opcode) || IS_ARTIFICIAL(opcode)); if (compiler_use_new_implicit_block_if_needed(c) < 0) { @@ -1442,6 +1452,7 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */ assert(IS_WITHIN_OPCODE_RANGE(opcode)); + assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(HAS_ARG(opcode)); assert(0 <= oparg && oparg <= 2147483647); @@ -1486,6 +1497,7 @@ static int add_jump_to_block(struct compiler *c, int opcode, basicblock *target) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); + assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(HAS_ARG(opcode) || IS_VIRTUAL_OPCODE(opcode)); assert(target != NULL); @@ -1915,7 +1927,7 @@ compiler_add_yield_from(struct compiler *c, int await) compiler_use_next_block(c, resume); ADDOP(c, YIELD_VALUE); ADDOP_I(c, RESUME, await ? 3 : 2); - ADDOP_JUMP(c, JUMP_BACKWARD_NO_INTERRUPT, start); + ADDOP_JUMP(c, JUMP_NO_INTERRUPT, start); compiler_use_next_block(c, exit); return 1; } @@ -7075,9 +7087,8 @@ stackdepth(struct compiler *c) stackdepth_push(&sp, instr->i_target, target_depth); } depth = new_depth; - assert(instr->i_opcode != JUMP_FORWARD); - assert(instr->i_opcode != JUMP_BACKWARD); - if (instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT || + assert(!IS_ASSEMBLER_OPCODE(instr->i_opcode)); + if (instr->i_opcode == JUMP_NO_INTERRUPT || instr->i_opcode == JUMP || instr->i_opcode == RETURN_VALUE || instr->i_opcode == RAISE_VARARGS || @@ -7583,15 +7594,15 @@ normalize_jumps(struct assembler *a) continue; } struct instr *last = &b->b_instr[b->b_iused-1]; - assert(last->i_opcode != JUMP_FORWARD); - assert(last->i_opcode != JUMP_BACKWARD); + assert(!IS_ASSEMBLER_OPCODE(last->i_opcode)); if (last->i_opcode == JUMP) { - if (last->i_target->b_visited == 0) { - last->i_opcode = JUMP_FORWARD; - } - else { - last->i_opcode = JUMP_BACKWARD; - } + 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; } } } @@ -8655,14 +8666,12 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts) inst->i_target = inst->i_target->b_next; } target = &inst->i_target->b_instr[0]; - assert(target->i_opcode != JUMP_FORWARD); - assert(target->i_opcode != JUMP_BACKWARD); + assert(!IS_ASSEMBLER_OPCODE(target->i_opcode)); } else { target = &nop; } - assert(inst->i_opcode != JUMP_FORWARD); - assert(inst->i_opcode != JUMP_BACKWARD); + assert(!IS_ASSEMBLER_OPCODE(inst->i_opcode)); switch (inst->i_opcode) { /* Remove LOAD_CONST const; conditional jump */ case LOAD_CONST: @@ -8963,8 +8972,7 @@ normalize_basic_block(basicblock *bb) { /* Mark blocks as exit and/or nofallthrough. Raise SystemError if CFG is malformed. */ for (int i = 0; i < bb->b_iused; i++) { - assert(bb->b_instr[i].i_opcode != JUMP_FORWARD); - assert(bb->b_instr[i].i_opcode != JUMP_BACKWARD); + assert(!IS_ASSEMBLER_OPCODE(bb->b_instr[i].i_opcode)); switch(bb->b_instr[i].i_opcode) { case RETURN_VALUE: case RAISE_VARARGS: @@ -8973,7 +8981,7 @@ normalize_basic_block(basicblock *bb) { bb->b_nofallthrough = 1; break; case JUMP: - case JUMP_BACKWARD_NO_INTERRUPT: + case JUMP_NO_INTERRUPT: bb->b_nofallthrough = 1; /* fall through */ case POP_JUMP_IF_NOT_NONE: @@ -9151,10 +9159,9 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts) for (basicblock *b = a->a_entry; b != NULL; b = b->b_next) { if (b->b_iused > 0) { struct instr *b_last_instr = &b->b_instr[b->b_iused - 1]; - assert(b_last_instr->i_opcode != JUMP_FORWARD); - assert(b_last_instr->i_opcode != JUMP_BACKWARD); + assert(!IS_ASSEMBLER_OPCODE(b_last_instr->i_opcode)); if (b_last_instr->i_opcode == JUMP || - b_last_instr->i_opcode == JUMP_BACKWARD_NO_INTERRUPT) { + b_last_instr->i_opcode == JUMP_NO_INTERRUPT) { if (b_last_instr->i_target == b->b_next) { assert(b->b_next->b_iused); b->b_nofallthrough = 0; From 506288a0733fe5532c269f108b20d9d2a949ac1d Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 1 Apr 2022 18:07:04 +0100 Subject: [PATCH 6/7] clarify that JUMP_BACKWARD does check for interrupts --- Doc/library/dis.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 1e5931f33137c8..e9953ba6f134a9 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -903,7 +903,7 @@ iterations of the loop. .. opcode:: JUMP_BACKWARD (delta) - Decrements bytecode counter by *delta*. + Decrements bytecode counter by *delta*. Checks for interrupts. .. versionadded:: 3.11 From 8d49d5ecbf8de2e29026270e0be2b2a9990f041e Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 5 Apr 2022 12:13:46 +0100 Subject: [PATCH 7/7] fix comment --- Lib/importlib/_bootstrap_external.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 1a319daae4e8e0..45be177df76a92 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -399,7 +399,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a6 3489 (Add JUMP_BACKWARD, remove JUMP_ABSOLUTE) # 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) +# add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual) # Python 3.12 will start with magic number 3500