]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-46031: add POP_JUMP_IF_NOT_NONE and POP_JUMP_IF_NONE (GH-30019)
authorpenguin_wwy <940375606@qq.com>
Thu, 6 Jan 2022 11:38:35 +0000 (19:38 +0800)
committerGitHub <noreply@github.com>
Thu, 6 Jan 2022 11:38:35 +0000 (11:38 +0000)
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/2021-12-10-09-10-32.bpo-46031.rM7JOX.rst [new file with mode: 0644]
Python/ceval.c
Python/compile.c
Python/opcode_targets.h

index 8490a09669656cd55d116e16083b47b139c42411..7afa62f95bc64c554cf536a7b517cedca05f8a88 100644 (file)
@@ -896,6 +896,20 @@ All of the following opcodes use their arguments.
    .. versionadded:: 3.11
 
 
+.. opcode:: POP_JUMP_IF_NOT_NONE (target)
+
+   If TOS is not none, sets the bytecode counter to *target*.  TOS is popped.
+
+   .. versionadded:: 3.11
+
+
+.. opcode:: POP_JUMP_IF_NONE (target)
+
+   If TOS is none, sets the bytecode counter to *target*.  TOS is popped.
+
+   .. versionadded:: 3.11
+
+
 .. opcode:: PREP_RERAISE_STAR
 
    Combines the raised and reraised exceptions list from TOS, into an exception
index 6794e828a72528500fb71f07c9a25ca6fa261229..98ff2d44a811baa11964ba4c24dfb85305e96225 100644 (file)
@@ -398,6 +398,9 @@ CPython bytecode changes
 * Added :opcode:`COPY`, which pushes the *i*-th item to the top of the stack.
   The item is not removed from its original location.
 
+* Add :opcode:`POP_JUMP_IF_NOT_NONE` and :opcode:`POP_JUMP_IF_NONE` opcodes to
+  speed up conditional jumps.
+
 * :opcode:`JUMP_IF_NOT_EXC_MATCH` no longer pops the active exception.
 
 
index 1af54943e1ca58cc36f401ef671b7b96d18c44fe..e4deeec932cea7c29067bdb2f4b56207a9e16140 100644 (file)
@@ -84,6 +84,8 @@ extern "C" {
 #define STORE_FAST                      125
 #define DELETE_FAST                     126
 #define JUMP_IF_NOT_EG_MATCH            127
+#define POP_JUMP_IF_NOT_NONE            128
+#define POP_JUMP_IF_NONE                129
 #define RAISE_VARARGS                   130
 #define MAKE_FUNCTION                   132
 #define BUILD_SLICE                     133
@@ -162,10 +164,10 @@ extern "C" {
 #define STORE_ATTR_SLOT                  80
 #define STORE_ATTR_WITH_HINT             81
 #define LOAD_FAST__LOAD_FAST             87
-#define STORE_FAST__LOAD_FAST           128
-#define LOAD_FAST__LOAD_CONST           129
-#define LOAD_CONST__LOAD_FAST           131
-#define STORE_FAST__STORE_FAST          134
+#define STORE_FAST__LOAD_FAST           131
+#define LOAD_FAST__LOAD_CONST           134
+#define LOAD_CONST__LOAD_FAST           140
+#define STORE_FAST__STORE_FAST          141
 #define DO_TRACING                      255
 #ifdef NEED_OPCODE_JUMP_TABLES
 static uint32_t _PyOpcode_RelativeJump[8] = {
@@ -183,7 +185,7 @@ static uint32_t _PyOpcode_Jump[8] = {
     0U,
     536870912U,
     2316288000U,
-    0U,
+    3U,
     0U,
     0U,
     0U,
index 872d6d96a74b4140ab117a005966319ee6db05fa..8e21be5916d31ca45cedcb8c081e3f0c56e1dc29 100644 (file)
@@ -378,6 +378,7 @@ _code_type = type(_write_atomic.__code__)
 #     Python 3.11a4 3470 (bpo-46221: PREP_RERAISE_STAR no longer pushes lasti)
 #     Python 3.11a4 3471 (bpo-46202: remove pop POP_EXCEPT_AND_RERAISE)
 #     Python 3.11a4 3472 (bpo-46009: replace GEN_START with POP_TOP)
+#     Python 3.11a4 3473 (Add POP_JUMP_IF_NOT_NONE/POP_JUMP_IF_NONE opcodes)
 
 #
 # MAGIC must change whenever the bytecode emitted by the compiler may no
@@ -387,7 +388,7 @@ _code_type = type(_write_atomic.__code__)
 # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
 # in PC/launcher.c must also be updated.
 
-MAGIC_NUMBER = (3472).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3473).to_bytes(2, 'little') + b'\r\n'
 _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 
 _PYCACHE = '__pycache__'
index f99e20ad0a670498d937273051b74f269e05b1c6..6030743b35c5bfb5632bdf1adb56e31139dafaf6 100644 (file)
@@ -148,9 +148,9 @@ def_op('STORE_FAST', 125)       # Local variable number
 haslocal.append(125)
 def_op('DELETE_FAST', 126)      # Local variable number
 haslocal.append(126)
-
 jabs_op('JUMP_IF_NOT_EG_MATCH', 127)
-
+jabs_op('POP_JUMP_IF_NOT_NONE', 128)
+jabs_op('POP_JUMP_IF_NONE', 129)
 def_op('RAISE_VARARGS', 130)    # Number of raise arguments (1, 2, or 3)
 
 def_op('MAKE_FUNCTION', 132)    # Flags
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-10-09-10-32.bpo-46031.rM7JOX.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-10-09-10-32.bpo-46031.rM7JOX.rst
new file mode 100644 (file)
index 0000000..65c8b38
--- /dev/null
@@ -0,0 +1 @@
+Add :opcode:`POP_JUMP_IF_NOT_NONE` and :opcode:`POP_JUMP_IF_NONE` opcodes to speed up conditional jumps.
\ No newline at end of file
index b4ac9ec848f773f0bfa012e8e20ccb9d62e15b36..86d834cd3a67ff817ac8dc3a73aa03960b34e739 100644 (file)
@@ -4049,6 +4049,30 @@ check_eval_breaker:
             DISPATCH();
         }
 
+        TARGET(POP_JUMP_IF_NOT_NONE) {
+            PyObject *value = POP();
+            if (!Py_IsNone(value)) {
+                Py_DECREF(value);
+                JUMPTO(oparg);
+                CHECK_EVAL_BREAKER();
+                DISPATCH();
+            }
+            Py_DECREF(value);
+            DISPATCH();
+        }
+
+        TARGET(POP_JUMP_IF_NONE) {
+            PyObject *value = POP();
+            if (Py_IsNone(value)) {
+                Py_DECREF(value);
+                JUMPTO(oparg);
+                CHECK_EVAL_BREAKER();
+                DISPATCH();
+            }
+            Py_DECREF(value);
+            DISPATCH();
+        }
+
         TARGET(JUMP_IF_FALSE_OR_POP) {
             PyObject *cond = TOP();
             int err;
index 3a390751fe2d22fa15f3286b5179ef33ff5c2734..625a07bd39675b7a9d520c4f50d21efb6dc198f4 100644 (file)
@@ -1110,6 +1110,8 @@ stack_effect(int opcode, int oparg, int jump)
 
         case POP_JUMP_IF_FALSE:
         case POP_JUMP_IF_TRUE:
+        case POP_JUMP_IF_NONE:
+        case POP_JUMP_IF_NOT_NONE:
             return -1;
 
         case LOAD_GLOBAL:
@@ -8519,6 +8521,21 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
                             bb->b_instr[i+1].i_opcode = NOP;
                         }
                         break;
+                    case IS_OP:
+                        cnt = get_const_value(inst->i_opcode, oparg, consts);
+                        if (cnt == NULL) {
+                            goto error;
+                        }
+                        int jump_op = i+2 < bb->b_iused ? bb->b_instr[i+2].i_opcode : 0;
+                        if (Py_IsNone(cnt) && (jump_op == POP_JUMP_IF_FALSE || jump_op == POP_JUMP_IF_TRUE)) {
+                            unsigned char nextarg = bb->b_instr[i+1].i_oparg;
+                            inst->i_opcode = NOP;
+                            bb->b_instr[i+1].i_opcode = NOP;
+                            bb->b_instr[i+2].i_opcode = nextarg ^ (jump_op == POP_JUMP_IF_FALSE) ?
+                                    POP_JUMP_IF_NOT_NONE : POP_JUMP_IF_NONE;
+                        }
+                        Py_DECREF(cnt);
+                        break;
                 }
                 break;
             }
@@ -8611,6 +8628,14 @@ optimize_basic_block(struct compiler *c, basicblock *bb, PyObject *consts)
                         break;
                 }
                 break;
+            case POP_JUMP_IF_NOT_NONE:
+            case POP_JUMP_IF_NONE:
+                switch (target->i_opcode) {
+                    case JUMP_ABSOLUTE:
+                    case JUMP_FORWARD:
+                        i -= jump_thread(inst, target, inst->i_opcode);
+                }
+                break;
             case POP_JUMP_IF_FALSE:
                 switch (target->i_opcode) {
                     case JUMP_ABSOLUTE:
@@ -8766,6 +8791,8 @@ normalize_basic_block(basicblock *bb) {
             case JUMP_FORWARD:
                 bb->b_nofallthrough = 1;
                 /* fall through */
+            case POP_JUMP_IF_NOT_NONE:
+            case POP_JUMP_IF_NONE:
             case POP_JUMP_IF_FALSE:
             case POP_JUMP_IF_TRUE:
             case JUMP_IF_FALSE_OR_POP:
index e9f1a483b970c74f8aaa743de8a11cf3cdff9005..7ba45666ed06153df6ab9db8abcf1aa99b22ebff 100644 (file)
@@ -127,20 +127,20 @@ static void *opcode_targets[256] = {
     &&TARGET_STORE_FAST,
     &&TARGET_DELETE_FAST,
     &&TARGET_JUMP_IF_NOT_EG_MATCH,
-    &&TARGET_STORE_FAST__LOAD_FAST,
-    &&TARGET_LOAD_FAST__LOAD_CONST,
+    &&TARGET_POP_JUMP_IF_NOT_NONE,
+    &&TARGET_POP_JUMP_IF_NONE,
     &&TARGET_RAISE_VARARGS,
-    &&TARGET_LOAD_CONST__LOAD_FAST,
+    &&TARGET_STORE_FAST__LOAD_FAST,
     &&TARGET_MAKE_FUNCTION,
     &&TARGET_BUILD_SLICE,
-    &&TARGET_STORE_FAST__STORE_FAST,
+    &&TARGET_LOAD_FAST__LOAD_CONST,
     &&TARGET_MAKE_CELL,
     &&TARGET_LOAD_CLOSURE,
     &&TARGET_LOAD_DEREF,
     &&TARGET_STORE_DEREF,
     &&TARGET_DELETE_DEREF,
-    &&_unknown_opcode,
-    &&_unknown_opcode,
+    &&TARGET_LOAD_CONST__LOAD_FAST,
+    &&TARGET_STORE_FAST__STORE_FAST,
     &&TARGET_CALL_FUNCTION_EX,
     &&_unknown_opcode,
     &&TARGET_EXTENDED_ARG,