]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44900: Add five superinstructions. (GH-27741)
authorMark Shannon <mark@hotpy.org>
Mon, 16 Aug 2021 11:23:13 +0000 (12:23 +0100)
committerGitHub <noreply@github.com>
Mon, 16 Aug 2021 11:23:13 +0000 (12:23 +0100)
* LOAD_FAST LOAD_FAST
* STORE_FAST LOAD_FAST
* LOAD_FAST LOAD_CONST
* LOAD_CONST LOAD_FAST
* STORE_FAST STORE_FAST

Include/opcode.h
Lib/opcode.py
Misc/NEWS.d/next/Core and Builtins/2021-08-12-14-00-57.bpo-44900.w2gpwy.rst [new file with mode: 0644]
Python/ceval.c
Python/opcode_targets.h
Python/specialize.c

index 50b783289590da9fe1b0ac768420b3100859f916..3334242e7e4d4022c59f5129675cc89a65314549 100644 (file)
@@ -153,6 +153,11 @@ extern "C" {
 #define STORE_ATTR_SPLIT_KEYS    45
 #define STORE_ATTR_SLOT          46
 #define STORE_ATTR_WITH_HINT     47
+#define LOAD_FAST__LOAD_FAST     48
+#define STORE_FAST__LOAD_FAST    58
+#define LOAD_FAST__LOAD_CONST    80
+#define LOAD_CONST__LOAD_FAST    81
+#define STORE_FAST__STORE_FAST   87
 #ifdef NEED_OPCODE_JUMP_TABLES
 static uint32_t _PyOpcode_RelativeJump[8] = {
     0U,
index 061506d0b88bd94627f0f9decd35ac041c9b91b9..53cdc4aa0d549d659353e1494a0dba7d42a43743 100644 (file)
@@ -237,8 +237,13 @@ _specialized_instructions = [
     "STORE_ATTR_SPLIT_KEYS",
     "STORE_ATTR_SLOT",
     "STORE_ATTR_WITH_HINT",
+    # Super instructions
+    "LOAD_FAST__LOAD_FAST",
+    "STORE_FAST__LOAD_FAST",
+    "LOAD_FAST__LOAD_CONST",
+    "LOAD_CONST__LOAD_FAST",
+    "STORE_FAST__STORE_FAST",
 ]
-
 _specialization_stats = [
     "specialization_success",
     "specialization_failure",
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-12-14-00-57.bpo-44900.w2gpwy.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-12-14-00-57.bpo-44900.w2gpwy.rst
new file mode 100644 (file)
index 0000000..8d94d6a
--- /dev/null
@@ -0,0 +1,7 @@
+Add five superinstructions for PEP 659 quickening:
+
+* LOAD_FAST LOAD_FAST
+* STORE_FAST LOAD_FAST
+* LOAD_FAST LOAD_CONST
+* LOAD_CONST LOAD_FAST
+* STORE_FAST STORE_FAST
index 111689ff629802dac6cde3fb2a85266b89bfbd0f..48787493fdd2ca2ac51ee98a7da44a062d47f660 100644 (file)
@@ -1266,16 +1266,21 @@ eval_frame_handle_pending(PyThreadState *tstate)
 #define PRE_DISPATCH_GOTO() do { LLTRACE_INSTR();  RECORD_DXPROFILE(); } while (0)
 #endif
 
+#define NOTRACE_DISPATCH() \
+    { \
+        frame->f_lasti = INSTR_OFFSET(); \
+        NEXTOPARG(); \
+        PRE_DISPATCH_GOTO(); \
+        DISPATCH_GOTO(); \
+    }
+
 /* Do interpreter dispatch accounting for tracing and instrumentation */
 #define DISPATCH() \
     { \
         if (cframe.use_tracing OR_DTRACE_LINE) { \
             goto tracing_dispatch; \
         } \
-        frame->f_lasti = INSTR_OFFSET(); \
-        NEXTOPARG(); \
-        PRE_DISPATCH_GOTO(); \
-        DISPATCH_GOTO(); \
+        NOTRACE_DISPATCH(); \
     }
 
 #define CHECK_EVAL_BREAKER() \
@@ -1682,11 +1687,7 @@ check_eval_breaker:
         TARGET(LOAD_FAST): {
             PyObject *value = GETLOCAL(oparg);
             if (value == NULL) {
-                format_exc_check_arg(tstate, PyExc_UnboundLocalError,
-                                     UNBOUNDLOCAL_ERROR_MSG,
-                                     PyTuple_GetItem(co->co_localsplusnames,
-                                                     oparg));
-                goto error;
+                goto unbound_local_error;
             }
             Py_INCREF(value);
             PUSH(value);
@@ -1708,6 +1709,73 @@ check_eval_breaker:
             DISPATCH();
         }
 
+        TARGET(LOAD_FAST__LOAD_FAST): {
+            PyObject *value = GETLOCAL(oparg);
+            if (value == NULL) {
+                goto unbound_local_error;
+            }
+            NEXTOPARG();
+            Py_INCREF(value);
+            PUSH(value);
+            value = GETLOCAL(oparg);
+            if (value == NULL) {
+                goto unbound_local_error;
+            }
+            Py_INCREF(value);
+            PUSH(value);
+            NOTRACE_DISPATCH();
+        }
+
+        TARGET(LOAD_FAST__LOAD_CONST): {
+            PyObject *value = GETLOCAL(oparg);
+            if (value == NULL) {
+                goto unbound_local_error;
+            }
+            NEXTOPARG();
+            Py_INCREF(value);
+            PUSH(value);
+            value = GETITEM(consts, oparg);
+            Py_INCREF(value);
+            PUSH(value);
+            NOTRACE_DISPATCH();
+        }
+
+        TARGET(STORE_FAST__LOAD_FAST): {
+            PyObject *value = POP();
+            SETLOCAL(oparg, value);
+            NEXTOPARG();
+            value = GETLOCAL(oparg);
+            if (value == NULL) {
+                goto unbound_local_error;
+            }
+            Py_INCREF(value);
+            PUSH(value);
+            NOTRACE_DISPATCH();
+        }
+
+        TARGET(STORE_FAST__STORE_FAST): {
+            PyObject *value = POP();
+            SETLOCAL(oparg, value);
+            NEXTOPARG();
+            value = POP();
+            SETLOCAL(oparg, value);
+            NOTRACE_DISPATCH();
+        }
+
+        TARGET(LOAD_CONST__LOAD_FAST): {
+            PyObject *value = GETITEM(consts, oparg);
+            NEXTOPARG();
+            Py_INCREF(value);
+            PUSH(value);
+            value = GETLOCAL(oparg);
+            if (value == NULL) {
+                goto unbound_local_error;
+            }
+            Py_INCREF(value);
+            PUSH(value);
+            NOTRACE_DISPATCH();
+        }
+
         TARGET(POP_TOP): {
             PyObject *value = POP();
             Py_DECREF(value);
@@ -4592,6 +4660,15 @@ binary_subscr_dict_error:
             goto error;
         }
 
+unbound_local_error:
+        {
+            format_exc_check_arg(tstate, PyExc_UnboundLocalError,
+                UNBOUNDLOCAL_ERROR_MSG,
+                PyTuple_GetItem(co->co_localsplusnames, oparg)
+            );
+            goto error;
+        }
+
 error:
         /* Double-check exception status. */
 #ifdef NDEBUG
index 24ee44f2d08c078e82c76816d087d77339024d9d..c8036a63f220115d2625d5fc2f3b7bc665b4018e 100644 (file)
@@ -47,7 +47,7 @@ static void *opcode_targets[256] = {
     &&TARGET_STORE_ATTR_SPLIT_KEYS,
     &&TARGET_STORE_ATTR_SLOT,
     &&TARGET_STORE_ATTR_WITH_HINT,
-    &&_unknown_opcode,
+    &&TARGET_LOAD_FAST__LOAD_FAST,
     &&TARGET_WITH_EXCEPT_START,
     &&TARGET_GET_AITER,
     &&TARGET_GET_ANEXT,
@@ -57,7 +57,7 @@ static void *opcode_targets[256] = {
     &&TARGET_INPLACE_ADD,
     &&TARGET_INPLACE_SUBTRACT,
     &&TARGET_INPLACE_MULTIPLY,
-    &&_unknown_opcode,
+    &&TARGET_STORE_FAST__LOAD_FAST,
     &&TARGET_INPLACE_MODULO,
     &&TARGET_STORE_SUBSCR,
     &&TARGET_DELETE_SUBSCR,
@@ -79,14 +79,14 @@ static void *opcode_targets[256] = {
     &&TARGET_INPLACE_AND,
     &&TARGET_INPLACE_XOR,
     &&TARGET_INPLACE_OR,
-    &&_unknown_opcode,
-    &&_unknown_opcode,
+    &&TARGET_LOAD_FAST__LOAD_CONST,
+    &&TARGET_LOAD_CONST__LOAD_FAST,
     &&TARGET_LIST_TO_TUPLE,
     &&TARGET_RETURN_VALUE,
     &&TARGET_IMPORT_STAR,
     &&TARGET_SETUP_ANNOTATIONS,
     &&TARGET_YIELD_VALUE,
-    &&_unknown_opcode,
+    &&TARGET_STORE_FAST__STORE_FAST,
     &&_unknown_opcode,
     &&TARGET_POP_EXCEPT,
     &&TARGET_STORE_NAME,
index e653ae41c57780491826e28815432e0393cade42..ecab69bcae78e4ce00711432a04bc519fc9c0127 100644 (file)
@@ -303,6 +303,7 @@ optimize(SpecializedCacheOrInstruction *quickened, int len)
     _Py_CODEUNIT *instructions = first_instruction(quickened);
     int cache_offset = 0;
     int previous_opcode = -1;
+    int previous_oparg = 0;
     for(int i = 0; i < len; i++) {
         int opcode = _Py_OPCODE(instructions[i]);
         int oparg = _Py_OPARG(instructions[i]);
@@ -338,14 +339,32 @@ optimize(SpecializedCacheOrInstruction *quickened, int len)
                 case JUMP_ABSOLUTE:
                     instructions[i] = _Py_MAKECODEUNIT(JUMP_ABSOLUTE_QUICK, oparg);
                     break;
-                /* Insert superinstructions here
-                 E.g.
                 case LOAD_FAST:
-                    if (previous_opcode == LOAD_FAST)
-                        instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_FAST, oparg);
-                 */
+                    switch(previous_opcode) {
+                        case LOAD_FAST:
+                            instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_FAST, previous_oparg);
+                            break;
+                        case STORE_FAST:
+                            instructions[i-1] = _Py_MAKECODEUNIT(STORE_FAST__LOAD_FAST, previous_oparg);
+                            break;
+                        case LOAD_CONST:
+                            instructions[i-1] = _Py_MAKECODEUNIT(LOAD_CONST__LOAD_FAST, previous_oparg);
+                            break;
+                    }
+                    break;
+                case STORE_FAST:
+                    if (previous_opcode == STORE_FAST) {
+                        instructions[i-1] = _Py_MAKECODEUNIT(STORE_FAST__STORE_FAST, previous_oparg);
+                    }
+                    break;
+                case LOAD_CONST:
+                    if (previous_opcode == LOAD_FAST) {
+                        instructions[i-1] = _Py_MAKECODEUNIT(LOAD_FAST__LOAD_CONST, previous_oparg);
+                    }
+                    break;
             }
             previous_opcode = opcode;
+            previous_oparg = oparg;
         }
     }
     assert(cache_offset+1 == get_cache_count(quickened));