]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-91276: Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative (GH-32215)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Fri, 15 Apr 2022 19:19:24 +0000 (20:19 +0100)
committerGitHub <noreply@github.com>
Fri, 15 Apr 2022 19:19:24 +0000 (20:19 +0100)
Doc/library/dis.rst
Doc/whatsnew/3.11.rst
Include/opcode.h
Lib/importlib/_bootstrap_external.py
Lib/opcode.py
Misc/NEWS.d/next/Core and Builtins/2022-03-31-14-33-48.bpo-47120.6S_uoU.rst [new file with mode: 0644]
Python/ceval.c
Python/compile.c

index 657778c0f4098a8e56e3ec8b3725fd28441bf4b4..08e6c736d3e3c9d2510970b0638ea9b0ffeedbaa 100644 (file)
@@ -993,21 +993,26 @@ iterations of the loop.
    .. versionadded:: 3.11
 
 
-.. opcode:: JUMP_IF_TRUE_OR_POP (target)
+.. opcode:: JUMP_IF_TRUE_OR_POP (delta)
 
-   If TOS is true, sets the bytecode counter to *target* and leaves TOS on the
+   If TOS is true, increments the bytecode counter by *delta* and leaves TOS on the
    stack.  Otherwise (TOS is false), TOS is popped.
 
    .. versionadded:: 3.1
 
+   .. versionchanged:: 3.11
+      The oparg is now a relative delta rather than an absolute target.
 
-.. opcode:: JUMP_IF_FALSE_OR_POP (target)
+.. opcode:: JUMP_IF_FALSE_OR_POP (delta)
 
-   If TOS is false, sets the bytecode counter to *target* and leaves TOS on the
+   If TOS is false, increments the bytecode counter by *delta* and leaves TOS on the
    stack.  Otherwise (TOS is true), TOS is popped.
 
    .. versionadded:: 3.1
 
+   .. versionchanged:: 3.11
+      The oparg is now a relative delta rather than an absolute target.
+
 
 .. opcode:: FOR_ITER (delta)
 
index b6f47f532ca4cc3dd5c7c1f0193dd2bf915b4f88..ca76efc963719a5d070decdec8678e1a9431535c 100644 (file)
@@ -787,6 +787,9 @@ CPython bytecode changes
   :opcode:`POP_JUMP_FORWARD_IF_NONE` and :opcode:`POP_JUMP_BACKWARD_IF_NONE`
   opcodes to speed up conditional jumps.
 
+* :opcode:`JUMP_IF_TRUE_OR_POP` and :opcode:`JUMP_IF_FALSE_OR_POP` are now
+  relative rather than absolute.
+
 
 Deprecated
 ==========
index 0badf78e32771384916f7f41b0fd03596194a080..8db42380cedd113951835a359b75890bd10cccd9 100644 (file)
@@ -199,7 +199,7 @@ static const uint32_t _PyOpcode_RelativeJump[8] = {
     0U,
     0U,
     536870912U,
-    135020544U,
+    135118848U,
     4163U,
     122880U,
     0U,
index d580e5417387bbee3077c041143072b75791dabb..4eece8de24c3e9a0d35be98336fb7591a444b557 100644 (file)
@@ -401,6 +401,7 @@ _code_type = type(_write_atomic.__code__)
 #     Python 3.11a6 3491 (remove JUMP_IF_NOT_EG_MATCH, add CHECK_EG_MATCH,
 #                         add JUMP_BACKWARD_NO_INTERRUPT, make JUMP_NO_INTERRUPT virtual)
 #     Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative)
+#     Python 3.11a7 3493 (Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative)
 
 #     Python 3.12 will start with magic number 3500
 
@@ -415,7 +416,8 @@ _code_type = type(_write_atomic.__code__)
 # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
 # in PC/launcher.c must also be updated.
 
-MAGIC_NUMBER = (3492).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3493).to_bytes(2, 'little') + b'\r\n'
+
 _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 
 _PYCACHE = '__pycache__'
index ee9effbe540b2f54a919f7e16ece19f88aa0789f..9ee06831c376875110b126e15305898aab6eb648 100644 (file)
@@ -131,8 +131,8 @@ hascompare.append(107)
 name_op('IMPORT_NAME', 108)     # Index in name list
 name_op('IMPORT_FROM', 109)     # Index in name list
 jrel_op('JUMP_FORWARD', 110)    # Number of words to skip
-jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code
-jabs_op('JUMP_IF_TRUE_OR_POP', 112)  # ""
+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)
 name_op('LOAD_GLOBAL', 116, 5)     # Index in name list
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-31-14-33-48.bpo-47120.6S_uoU.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-31-14-33-48.bpo-47120.6S_uoU.rst
new file mode 100644 (file)
index 0000000..c87d984
--- /dev/null
@@ -0,0 +1 @@
+Make opcodes :opcode:`JUMP_IF_TRUE_OR_POP` and :opcode:`JUMP_IF_FALSE_OR_POP` relative rather than absolute.
index 7891547ffc687174baa12e2d2783904f5e3fd9f3..66856e5177607f6c6f265f8f54d0a9ebc0b4ec92 100644 (file)
@@ -4081,7 +4081,7 @@ handle_eval_breaker:
                 DISPATCH();
             }
             if (Py_IsFalse(cond)) {
-                JUMPTO(oparg);
+                JUMPBY(oparg);
                 DISPATCH();
             }
             err = PyObject_IsTrue(cond);
@@ -4090,7 +4090,7 @@ handle_eval_breaker:
                 Py_DECREF(cond);
             }
             else if (err == 0)
-                JUMPTO(oparg);
+                JUMPBY(oparg);
             else
                 goto error;
             DISPATCH();
@@ -4105,12 +4105,12 @@ handle_eval_breaker:
                 DISPATCH();
             }
             if (Py_IsTrue(cond)) {
-                JUMPTO(oparg);
+                JUMPBY(oparg);
                 DISPATCH();
             }
             err = PyObject_IsTrue(cond);
             if (err > 0) {
-                JUMPTO(oparg);
+                JUMPBY(oparg);
             }
             else if (err == 0) {
                 STACK_SHRINK(1);
index 718b521858b27d42c6c4d2ff6529c3532b074b7f..3b91566efba2942e46c03e725dfe6aa216da230e 100644 (file)
@@ -7672,6 +7672,21 @@ normalize_jumps(struct assembler *a)
                     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;
             }
         }
     }